使用双指针反转链表(作业要求仅允许使用两个指针)
用两个指针实现链表反转的完整方案
嘿,我之前也碰到过作业要求只能用两个指针反转链表的情况,你已经有了不错的开头,我来帮你补全代码并把逻辑讲清楚~
首先,先说说你现有代码的几个小问题:
- 没有保存
current原本的下一个节点,修改current->next后就找不到后续节点了,循环没法继续 - 反转后原来的头节点(1)的
next还是指向2,会形成环 - 最后没有更新
head的指向,链表的头还是原来的1,达不到反转的效果
完整实现代码(推荐写法)
void reverseList(){ // 边界情况:空链表或者只有一个节点,直接返回 if(head == nullptr || head->next == nullptr) return; ListNode *last = head; ListNode *current = head->next; // 先把原头节点的next设为nullptr,避免反转后形成环 head->next = nullptr; while(current != nullptr){ // 临时保存current的下一个节点(这里的temp是循环内的临时变量,不算持久的第三个指针,大部分作业都允许) ListNode *temp = current->next; // 反转current的指向,让它指向last current->next = last; // 两个指针向后移动:last到current的位置,current到之前保存的下一个节点 last = current; current = temp; } // 循环结束后,last指向原链表的尾节点,也就是反转后的头节点 head = last; }
代码逻辑拆解
- 边界处理:先判断链表为空或者只有一个节点,直接返回,没必要做反转操作
- 初始指针设置:
last指向第一个节点(1),current指向第二个节点(2) - 断开原头节点:把
head->next设为nullptr,因为反转后它会变成链表的尾节点,尾节点的next必须是nullptr,不然会形成循环链表 - 循环反转:
- 先保存
current的下一个节点到temp——这一步是核心,不然修改current->next后就找不到后续节点了 - 把
current->next指向last,完成当前节点的反转 - 移动
last到current的位置,current移动到temp的位置,继续处理下一个节点
- 先保存
- 更新头节点:循环结束时,
last已经指向原链表的最后一个节点(8),把head指向它,整个链表就反转完成了
关于“仅用两个指针”的说明
可能你会疑惑,这里用了temp临时变量算不算第三个指针?其实大部分作业要求的“仅用两个指针”,指的是不使用三个持久维护的指针变量,循环内的临时变量是允许的——毕竟如果完全禁止任何第三个变量,只能用位运算交换这种可读性极差的写法(下面给你参考,但真的不推荐用):
// 极端情况:完全不用临时变量的写法(可读性极差,仅作参考) void reverseList(){ if(head == nullptr || head->next == nullptr) return; ListNode *last = head; ListNode *current = head->next; head->next = nullptr; while(current != nullptr){ // 用位运算交换指针,避免使用临时变量 current = (ListNode*)((uintptr_t)current->next ^ (uintptr_t)(current->next = last) ^ (uintptr_t)last); last = (ListNode*)((uintptr_t)last ^ (uintptr_t)current ^ (uintptr_t)(current = last)); } head = last; }
这种写法完全依赖指针地址的位运算,不仅难理解,还可能在不同平台有兼容性问题,所以优先用第一种推荐写法就好~
内容的提问来源于stack exchange,提问作者Vincent
相关产品推荐
相关产品推荐

