反转链表相关函数的执行行为与实现逻辑咨询
问题背景
我在学习数据结构与算法的过程中,尝试分析下方反转链表相关函数的具体功能、执行流程与运行逻辑,暂未完全理清其实现原理,恳请各位帮忙解释该函数的实际作用与运行行为,非常感谢!
函数作用
这是单链表反转的经典递归实现,输入单链表的头节点指针,最终返回反转完成后链表的新头节点(也就是原链表的尾节点)。
逐行逻辑与执行流程
先贴出截图里的完整代码,方便对照说明:
// 单链表节点定义 struct ListNode { int val; struct ListNode *next; }; struct ListNode* reverseList(struct ListNode* head) { // 递归终止边界 if (head == NULL || head->next == NULL) { return head; } // 先递归处理当前节点后面的子链表 struct ListNode* newHead = reverseList(head->next); // 反转当前节点和后继节点的指针方向 head->next->next = head; // 把当前节点的next置空,避免出现环 head->next = NULL; // 一路返回反转后的链表头 return newHead; }
具体运行逻辑可以拆成几步:
- 递归到最深处触底:函数拿到当前节点后,不会先修改指针,而是一直往链表尾部递归,直到碰到两种情况直接返回:要么传入的是空链表直接返回空,要么碰到原链表的尾节点(它的
next指针是空),这个尾节点就是反转后整个链表的新头,后续所有递归层都要把这个值往上层传递。 - 回溯阶段逐层改指针:等深层递归返回结果时,说明当前节点后面的所有节点已经完成反转了。举个例子,当前处理的节点是A,A原来的下一个节点是B,递归处理完A后面的部分后,B已经变成了反转后子链表的尾节点,这时候只要把B的
next指向A,就把A接到了反转后子链表的末尾。 - 避免链表环:改完指针后必须把当前节点A的
next置为空,因为现在A是已反转部分的尾节点,尾节点的next本来就应该是空,如果不做这步,A和B之间会形成双向指向的环,遍历链表的时候会陷入死循环。 - 逐层返回新头:每一层处理完都把之前拿到的反转后子链表头
newHead返回给上一层,等回到最外层的初始调用时,拿到的就是整个链表反转完成后的头节点。
举个实际运行的例子更清楚,原链表是1 -> 2 -> 3 -> NULL:
- 初始调用传入节点1,不满足终止条件,先递归调用处理节点2
- 处理节点2时不满足终止条件,递归调用处理节点3
- 处理节点3时,发现3的
next是空,直接返回3作为newHead - 回到节点2的处理层:让3的
next指向2,把2的next置空,此时反转后的子链表是3 -> 2 -> NULL,向上返回newHead=3 - 回到节点1的处理层:让2的
next指向1,把1的next置空,此时整个链表变成3 -> 2 -> 1 -> NULL,向上返回newHead=3 - 初始调用拿到返回值3,整个反转流程结束。
内容的提问来源于stack exchange,提问作者Quoc Tuan
相关产品推荐
相关产品推荐

