【问题标题】:Help in understanding code snippet that reverses linked list using recursion帮助理解使用递归反转链表的代码片段
【发布时间】:2011-01-24 07:46:13
【问题描述】:

我正在学习 C 中的链接列表的考试。我发现自己是一个“审阅者”,它有这个 sn-p 代码。对于我的一生,我无法理解其余部分是如何逆转的。在这里……它来自 Nick Parlante 先生的 Linked List Problems(取自斯坦福大学 CIS 图书馆)。 我会加入尼克先生的评论。

RecursiveReverse() 解决方案

可能最困难的部分是接受这样一个概念: RecursiveReverse(&rest) 实际上确实反转了其余部分。然后有一个技巧 让一个前端节点一直到列表的末尾。画个图看看怎么做 诀窍奏效了。

void RecursiveReverse(struct node** headRef) {
struct node* first;
struct node* rest;
if (*headRef == NULL) return; // empty list base case
first = *headRef; // suppose first = {1, 2, 3}
rest = first->next; // rest = {2, 3}
if (rest == NULL) return; // empty rest base case
RecursiveReverse(&rest); // Recursively reverse the smaller {2, 3} case
                         // after: rest = {3, 2}
first->next->next = first; // put the first elem on the end of the list
first->next = NULL; // (tricky step -- make a drawing)
*headRef = rest; // fix the head pointer 

}

我已经画了无数张图来试图追踪正在发生的事情,但我无法理解 RecursiveRest(&rest) 实际上是如何反转其余部分的。请帮忙。我越来越沮丧。我最终得到的是更小的“休息”……没有什么是逆转的。 非常感谢您。

【问题讨论】:

    标签: c recursion linked-list reverse


    【解决方案1】:

    递归通常很难理解,因为很难看出它是如何分解成基本步骤的。

    通常更容易将递归部分视为已经完成并且仅对组合步骤进行推理(这在设计算法时最有用)。

    当您尝试可视化递归算法的工作原理时,您必须记住有两个过程在起作用:

    • 将原始问题分解为较小的问题,直到找到终止案例
    • 终止案例的解决
    • 结果的组合。

    这就像一条双向街道。首先,您在解决问题的同时走一条路,直到最终案例。然后,您解决最终情况。之后,您在组合部分结果时从头返回。

    你的情况可能是这样的。请注意,[A-B] 表示一个列表。

    [A-B-C-D-E] // RecursiveReverse([A, B, C, D, E])
    (A [B-C-D-E]) // this means we are calling RecursiveReverse([B, C, D, E])
    (A (B [C-D-E])) // this means we are calling RecursiveReverse([C, D, E])
    (A (B (C [D-E]))) // this means we are calling RecursiveReverse([D, E])
    (A (B (C (D [E])))) // this means we are calling RecursiveReverse([E]) 
                        // hit the end case and solve it trivially
    (A (B (C (D [E])))) // solved
    (A (B (C [E-D]))) // and go back while applying the combination case
    (A (B [E-D-C])) // combine
    (A [E-D-C-B]) // combine
    [E-D-C-B-A] // combine
    

    希望这会有所帮助。

    【讨论】:

    • @sarnold 谢谢 :)。我尽量提供一点帮助:)。
    【解决方案2】:
    1. 代码在每一步都会记住 当前和下一个节点(第一个和 休息)。
    2. 假设 RecursiveReverse(&rest) 工作并反转剩余的列表。
    3. 那么其余节点将位于 调用返回时的最后位置。 所以你只需要检查最后一个 三行代码。
    4. 您将看到 rest 更改为 首先指向 (first->next->next = first),并且 first 指向 NULL (first->next = NULL),即你先移动到最后 的列表。

    【讨论】:

    • 非常感谢。这真的很有帮助,我明白现在发生了什么。 :)
    猜你喜欢
    • 2014-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多