代码之家  ›  专栏  ›  技术社区  ›  Akshay Parashar

反转链表的递归函数(代码段解释)[已关闭]

  •  0
  • Akshay Parashar  · 技术社区  · 8 年前

    有人能解释一下下面的代码吗

    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?

    1 回复  |  直到 8 年前
        1
  •  2
  •   molbdnilo    8 年前

    reverseList 将更新 *href 因此,它指向了给定列表中的新标题;这是过去最后一个节点。
    我认为让你困惑的是,所有的电话都在更新 至相同值;当递归调用返回时,它将指向输入的最后一个节点,即结果的第一个节点。
    该值仅在递归终止时设置。

    我要重新命名 first 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_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;