反向链表的递归函数(代码片段说明)

时间:2017-11-07 14:07:39

标签: 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->next->next = first;
   first->next = NULL;


   *href = rest;
}

注意:href是链接列表的头部引用。

我不明白的是最后一句话=> *href = rest 因为这个步骤将在递归展开时发生,这不会使第二个节点从起始头ref开始,但我们希望最后一个节点作为我们的头部参考。

这将如何使最后一个节点成为head_ref?

1 个答案:

答案 0 :(得分:2)

reverseList将更新*href,因此它指向其给出的列表的新头部;这是过去的节点。
我认为令人困惑的是,所有调用都会将*href更新为相同的值;当递归调用返回时,它将指向输入的最后一个节点,这是结果的第一个节点 仅在递归终止时设置此值。

我要重命名firstrest,以澄清这一点。

第一个条件,

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_head = old_head->next;
reverseList(&new_head);

现在,通过递归的力量,new_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_head->next->next = old_head;

old_head                                             new_head 
  |                                                    |
  v                                                    v
+---+    +---+         +-----------------------------+
| ------>|   |  <----- |         reversed            |
|   |<-----  |         | former continuation of list |
+---+    +---+         +-----------------------------+

然后(old_head->next = NULL;

old_head                                             new_head 
  |                                                    |
  v                                                    v
+---+    +---+         +-----------------------------+
| X |    |   |  <----- |         reversed            |
| X |<-----  |         | former continuation of list |
+---+    +---+         +-----------------------------+

然后,我们更新参数,以便我们的调用者也获得指向新头的指针:

*href = new_head;