反转链表(LeetCode 206)C语言解题思路

反转链表是基础算法题,关键在于理解指针操作。以下是适合初学者的详细思路和代码实现:


方法一:迭代法(推荐)

核心思想:使用三个指针(prev, curr, next)逐个节点反转指向。

步骤 : 初始化prev为NULL,curr指向头节点。 遍历链表时,先用next暂存curr->next,再将curr->next指向prev。 最后移动prevcurr到下一个位置。

代码

c 复制代码
struct ListNode* reverseList(struct ListNode* head) {
    struct ListNode *prev = NULL;           //struct ListNode* 代表:返回一个【节点的地址】
    struct ListNode *curr = head;           
    while (curr != NULL) {                  //prev移动到最后一个节点时,curr为null
        struct ListNode *next = curr->next; // 暂存下一个节点
        curr->next = prev;                  // 反转指向
        prev = curr;                        // 移动prev
        curr = next;                        // 移动curr
    }
    return prev; // 新头节点
}

难点解析:

1.普通数组:一整块连续的内存,像一串连在一起的车厢,紧紧挨在一起。

链表:一节一节独立的节点,每一节只记住下一节在哪里。

节点是一个小包裹,包裹里面装两样东西:

  1. 真正的数据:数字 val(比如 1、2、3)
  2. 一张小纸条:存着下一个包裹的地址 next

只要拿到第一个包裹(头节点),就能顺着它里面的 next 纸条,找到后面所有包裹。


方法二:递归法

核心思想:递归到链表末端,从后向前反转指针。

步骤 : 递归终止条件是当前节点为空或下一个节点为空。 在回溯过程中,将当前节点的下一节点的next指向自己,并断开原指向。

代码

c 复制代码
struct ListNode* reverseList(struct ListNode* head) {
    if (head == NULL || head->next == NULL) {    //避免head直接为空节点情况
        return head;
    }
    struct ListNode *newHead = reverseList(head->next);
    head->next->next = head; // 反转指向   这两行代码只有在满足if函数后,返回上一层的时候才施行
    head->next = NULL;       // 断开原指向
    return newHead;
}

1->2->3->NULL。意思就是head=1时,head->next不满足NULL,到下一层;head=2时,head->next不满足NULL,到下一层;head=3时,head->next==NULL,输出newHead=3,因为节点包括数字与下一个数字地址,所以输出为3后返回上一层;上一层为head2时,执行反转,3->next=2->next=NULL;最后到head=1同理,2->next=1->next=NULL


注意事项:

函数名字叫 reverseList它自己就是反转函数

  • 你定义了一个叫 reverseList 的工具,功能是反转链表;
  • 在工具内部,你又调用了这个工具本身,这就叫递归。

递归先一路钻到最后一个节点,全程不做反转; 只有走到链表末尾 return 之后,才一层一层回头颠倒箭头; newHead 永远是原链表最后一个节点(反转后的表头),每层都原样往上传递; head->next->next = head 就是把下一个节点反过来指向自己; head->next = nullptr 切断原来向后的连线,避免循环死链表。