反转链表-用二重指针解决
反转链表-用二重指针解决
问题引入
输入一个链表,反转链表后,输出新链表的表头
一般情况下的解决办法
用if处理特殊情况
- head为空的情况
- 只有一个节点的情况
用prev、curr、next来进行游走,维护链表
1 之前是这样的
ListNode* curr = head;
ListNode* prev = NULL;
ListNode* next = head->next;
2 维护过程
while (next)
{
curr->next = prev;
prev = curr;
curr = next;
next = next->next;
}
curr->next = prev;
让curr用于调整指针,将当前节点的next指针从指向next,转变成指向prev
让next扮演“开路先锋”,一直走到“黑”
3 结果
链表被反转了
ListNode* ReverseList(ListNode* head) {
/*链表少于一个节点*/
if (!head||!head->next)
{
return head;
}
ListNode* curr = head;
ListNode* prev = NULL;
ListNode* next = head->next;
while (next)
{
curr->next = prev;
prev = curr;
curr = next;
next = next->next;
}
curr->next = prev;
return curr;
}
其实一般解法挺好理解的,就是用3个指针来维护链表。
二重指针
假设链表中每个节点都是
它由NEXT字段和DATA字段组成
NEXT指向的是下一节点,本质上,NEXT字段存储了下一个节点的内存地址
所以 ListNode** curr = &head;
这个二重指针,就是把头节点地址的指针的地址,存储在了curr里面。
点到为止,想详细了解二重指针和链表关系的,可参考之前我写的文章:
linus提到过的单链表删除节点算法 - wqybokeyuan - 博客园 (cnblogs.com)
最终代码:
ListNode* ReverseList(ListNode* pHead) {
ListNode** curr = &pHead;
ListNode* prev_1 = NULL;
ListNode* prev_2 = NULL;
while (*curr)
{
ListNode* temp = *curr;
*curr = prev_2;
prev_2 = prev_1;
prev_1 = temp;
curr = &(temp->next);
}
*curr = prev_2;
return prev_1;
}
用了1个curr二重指针和3个临时变量来维护链表,只是二重指针不需要用if判断是否为空,显得更牛逼一些罢了,其实本质上与上面的一般解法没啥区别~
做完题目,提交,一次性通过。这个奖杯,让我觉得很惊喜,很开心。大概这就是程序员的快乐吧 : )