反转链表是基础算法题,关键在于理解指针操作。以下是适合初学者的详细思路和代码实现:
方法一:迭代法(推荐)
核心思想:使用三个指针(prev, curr, next)逐个节点反转指向。
步骤: 初始化prev为NULL,curr指向头节点。 遍历链表时,先用next暂存curr->next,再将curr->next指向prev。 最后移动prev和curr到下一个位置。
代码:
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.普通数组:一整块连续的内存,像一串连在一起的车厢,紧紧挨在一起。
链表:一节一节独立的节点,每一节只记住下一节在哪里。
2.
节点是一个小包裹,包裹里面装两样东西:
- 真正的数据:数字 val(比如 1、2、3)
- 一张小纸条:存着下一个包裹的地址 next
只要拿到第一个包裹(头节点),就能顺着它里面的 next 纸条,找到后面所有包裹。
方法二:递归法
核心思想:递归到链表末端,从后向前反转指针。
步骤: 递归终止条件是当前节点为空或下一个节点为空。 在回溯过程中,将当前节点的下一节点的next指向自己,并断开原指向。
代码:
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 切断原来向后的连线,避免循环死链表。
830

被折叠的 条评论
为什么被折叠?



