C++ 反转链表的递归函数(代码段解释)
有人能解释一下下面的代码吗C++ 反转链表的递归函数(代码段解释),c++,algorithm,recursion,linked-list,code-snippets,C++,Algorithm,Recursion,Linked List,Code Snippets,有人能解释一下下面的代码吗 void reverseList(node **href){ node *first; node *rest; if(*href == NULL){ return; } first = *href; rest = first->next; if(rest == NULL){ return; } reverseList(&rest); first->nex
void reverseList(node **href){
node *first;
node *rest;
if(*href == NULL){
return;
}
first = *href;
rest = first->next;
if(rest == NULL){
return;
}
reverseList(&rest);
first->next->next = first;
first->next = NULL;
*href = rest;
}
注意:href是链接列表的标题参考。
我不明白的是最后一句话=>*href=rest
由于这一步将在递归展开时发生,这不会使第二个节点从开始head ref开始,但我们希望最后一个节点作为head ref
这将如何使最后一个节点成为我们的head\u ref?
reverseList
将更新*href
,从而指向给定列表的新head;这是过去最后一个节点。我想可能会让你困惑的是,所有调用都将
*href
更新为相同的值;当递归调用返回时,它将指向输入的最后一个节点,即结果的第一个节点。此值仅在递归终止时设置 为了澄清这一点,我将首先重命名
和rest
第一个条件,
if(*href == NULL){
return;
}
当你从空名单开始的时候,有没有人来处理这个问题
以下内容处理公共基本情况,您最终将获得一个元素列表:
old_head = *href;
/* "If the list has exactly one element, do nothing." */
if(old_head->next == NULL){
return;
}
然后,递归(请记住,该参数既是“in”参数又是“out”参数)
现在,通过递归的力量,new\u head
指向相反的“列表的其余部分”的头部。
这也是将成为我们结果的指针。
(尾部的最后一个节点也是整个列表的最后一个节点,对吗?)
我们现在需要的是设置新列表的结尾(它的初始部分在递归过程中已经反转)
由于我们以前保存了old_head
,因此可以反转用于跟随它的节点的next
指针:
old_head->next->next = old_head;
old_head->next = NULL;
就是这个
old_head new_head
| |
v v
+---+ +---+ +-----------------------------+
| ------>| | <----- | reversed |
| | | -----> | former continuation of list |
+---+ +---+ +-----------------------------+
然后(old\u head->next=NULL;
)
reverseList
将更新*href
,使其指向给定列表的新标题;这是过去最后一个节点。
我想可能会让你困惑的是,所有调用都将*href
更新为相同的值;当递归调用返回时,它将指向输入的最后一个节点,即结果的第一个节点。
此值仅在递归终止时设置
为了澄清这一点,我将首先重命名和rest
第一个条件,
if(*href == NULL){
return;
}
当你从空名单开始的时候,有没有人来处理这个问题
以下内容处理公共基本情况,您最终将获得一个元素列表:
old_head = *href;
/* "If the list has exactly one element, do nothing." */
if(old_head->next == NULL){
return;
}
然后,递归(请记住,该参数既是“in”参数又是“out”参数)
现在,通过递归的力量,new\u head
指向相反的“列表的其余部分”的头部。
这也是将成为我们结果的指针。
(尾部的最后一个节点也是整个列表的最后一个节点,对吗?)
我们现在需要的是设置新列表的结尾(它的初始部分在递归过程中已经反转)
由于我们以前保存了old_head
,因此可以反转用于跟随它的节点的next
指针:
old_head->next->next = old_head;
old_head->next = NULL;
就是这个
old_head new_head
| |
v v
+---+ +---+ +-----------------------------+
| ------>| | <----- | reversed |
| | | -----> | former continuation of list |
+---+ +---+ +-----------------------------+
然后(old\u head->next=NULL;
)
请帮你自己(和我们)一个忙,格式化你的代码……并在打电话到reverseList(&ptr)后发布一条消息
,ptr
指向新反转列表的头部,即原始列表中最后一个节点,现在是第一个节点<代码>*href=rest需要code>来维护此不变量。请注意,rest
本身被递归的reverseList(&rest)
调用修改,现在指向反向的“倒数第二”列表的头部。抓起一张纸和一支笔。当您浏览一个示例时,代码比您试图从理论的角度理解它时容易得多。请帮您自己(和我们)一个忙,格式化您的代码……并在调用reverseList(&ptr)后发布一条消息
,ptr
指向新反转列表的头部,即原始列表中最后一个节点,现在是第一个节点<代码>*href=rest需要code>来维护此不变量。请注意,rest
本身被递归的reverseList(&rest)
调用修改,现在指向反向的“倒数第二”列表的头部。抓起一张纸和一支笔。当您浏览一个示例时,代码比您试图从理论的角度理解它时更容易理解。谢谢您的详细回答。它帮助我意识到我遗漏了什么。谢谢你详细的回答。它帮助我意识到我错过了什么。