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来维护此不变量。请注意,
rest
本身被递归的
reverseList(&rest)
调用修改,现在指向反向的“倒数第二”列表的头部。抓起一张纸和一支笔。当您浏览一个示例时,代码比您试图从理论的角度理解它时容易得多。请帮您自己(和我们)一个忙,格式化您的代码……并在调用reverseList(&ptr)后发布一条消息
ptr
指向新反转列表的头部,即原始列表中最后一个节点,现在是第一个节点<代码>*href=rest来维护此不变量。请注意,
rest
本身被递归的
reverseList(&rest)
调用修改,现在指向反向的“倒数第二”列表的头部。抓起一张纸和一支笔。当您浏览一个示例时,代码比您试图从理论的角度理解它时更容易理解。谢谢您的详细回答。它帮助我意识到我遗漏了什么。谢谢你详细的回答。它帮助我意识到我错过了什么。