反转单链表的核心逻辑是用三个指针(prev、cur、next_temp)迭代“掰弯”next指针:先保存cur->next,再改cur->next=prev,最后更新prev=cur、cur=next_temp;初始化prev=nullptr、cur=head,循环条件为while(cur!=nullptr),结束时prev即新头。

反转单链表的核心逻辑是什么
不是靠递归“想明白”,而是用三个指针现场“掰弯”每个节点的 next 指针方向。关键在于:在修改当前节点 next 之前,必须先保存它原本指向的下一个节点,否则链表就断了。
典型错误是写成:cur->next = prev; cur = cur->next; —— 这里 cur->next 已被改写,cur = cur->next 就跳飞了,直接丢失后续所有节点。
正确做法是用临时变量提前存住下一节点:
ListNode* next_temp = cur->next; cur->next = prev; prev = cur; cur = next_temp;
迭代法实现要注意的边界和初始化
空链表或单节点链表要能自然通过,不需要额外 if 判断。关键是初始化:prev 必须为 nullptr,cur 从 head 开始。
立即学习“C++免费学习笔记(深入)”;
-
prev初始值不能是head或任意节点,否则反转后尾节点会自环 - 循环条件用
while (cur != nullptr),不是cur->next != nullptr,否则最后一个节点会被跳过 - 退出循环后,
prev正好是新链表头,直接返回即可
递归写法为什么容易栈溢出且难调试
递归本质是把“等后面翻完再改自己”压进调用栈,每层都要存一个栈帧。对长度为 N 的链表,递归深度就是 N —— 链表一过万节点,std::bad_alloc 或栈溢出就来了。
更隐蔽的问题是:递归版本必须确保原链表无环,否则会无限递归;而且翻转过程中中间态不可见,出错时很难定位是哪一层改错了 next。
如果坚持用递归,务必检查输入是否含环(可用快慢指针预判),并限制最大深度(比如加个计数器,超 1000 层就抛异常)。
反转后怎么验证结果是否正确
别只看头节点输出,容易漏掉环或断链。最简验证方式是遍历两次:
- 第一次正向遍历,记录所有值到
std::vector - 反转后第二次正向遍历,把值再存一份
- 对比两个 vector 是否互为逆序 —— 这比肉眼检查指针更可靠
特别注意:若原始链表有重复值,仅比值不够,得加地址打印(如 printf("%p -> ", (void*)node))确认物理连接关系。
实际工程中,反转操作常出现在链表合并、K 个一组翻转等复合场景里,这时候 prev/cur 的初始状态、循环终止条件都可能变化,不能死记模板。











