递归如何以相反的顺序打印链表元素?

时间:2017-01-02 12:48:16

标签: java recursion singly-linked-list

我对递归的工作原理有一点了解。调用以及堆栈提供的变量的不同上下文,用于存储前一个被调用函数返回的值。

例如,

void Factorial(int n)
{
  if(n==0) return 0;
  else if(n==1) return 1;
  else
  {
    return n*Factorial(n-1);
  }
}

在这个用于计算给定数的阶乘的递归函数中,我知道假设给定n为5的第一次调用将是5 *因子(4 *因子(3 ....所以直到它到达任何基本条件))然后它将按顺序遍历返回值,例如1 * 2 * 3 * 4 * 5 = 240。

我无法理解的是这段代码以相反的顺序打印单链表的项目。

void ReversePrint(Node head) {    
if(head==null)
    {
    return;
    }
else
    {
    ReversePrint(head.next);
    System.out.println(head.data);
    }
}

据我所知,链表函数中的元素数量有限,如

首先, 因为head不是null,所以它将转到else条件,head将等于head.next,直到它变为null。什么呢?

我可能不会用确切的语言表达我的问题。希望你能解释一下。提前谢谢。

3 个答案:

答案 0 :(得分:2)

添加一些额外的评论应该会有所帮助:

void ReversePrint(Node node) {
    if (node == null) {
        // An empty list has nothing to print.
        return;
    } else {
        // First print the rest of the list.
        ReversePrint(node.next);
        // Then print this node.
        System.out.println(node.data);
    }
}

所以 - 基本上 -

  • 空列表不打印任何内容。
  • 非空列表应打印列表的其余部分 first ,然后打印根节点。

导致列表向后打印。

答案 1 :(得分:0)

想象一下,你有一个名为ReversePrintRest的函数,它会获取一个列表并打印所有的头部。然后你可以很容易地写ReversePrint

void ReversePrint(Node head) {    
    if(head==null) {
        return;
    } else {
        ReversePrintRest(head);
        System.out.println(head.data);
    }
}

只要ReversePrintRest像宣传的那样工作,我就会认为你同意这个有效是没有问题的。

关于如何编写ReversePrintRest,这也很简单:

void ReversePrintRest( Node head ) {
    ReversePrint( head.next );
}

同样,假设ReversePrint有效,也很容易看出正确性。由于ReversePrintRest的正文是直接从原始代码中获取的,因此原始代码也应该是正确的。

这似乎有些狡猾:每个功能的正确性取决于其他功能。但我们可以更明确地了解ReversePrint

  • 它显然适用于空列表
  • 假设它适用于较短的列表,它适用于当前的列表,依赖于已知可用于较短列表的代码并使用它做正确的事情(即,反向打印头部)打印其余部分)。

只留下假设:

  • 我们知道它适用于空列表
  • 由于它适用于空列表,因此适用于长度为1的列表。
  • 由于它适用于长度为1的列表,因此适用于长度为2的列表。

只要您需要任何长度为N的列表,您就可以遵循该逻辑。由于参数不依赖于N的特定值,因此它适用于所有这些值。

答案 2 :(得分:-1)

这个问题可能有很多重复,但不是找到它们并将它们联系起来,我想解决一些与你所问的问题有关的问题。

对于阶乘示例,递归很有效,因为通常你不想计算非常高的阶乘,如果你确实希望你在进入堆栈之前经常遇到整数溢出溢出。

但是,列表的大小通常大于1000个元素。对于我的实现,ReversePrint方法给了我一个大于大约10000个元素的StackOverflowError链表,这是由于Java限制了内存中的堆栈大小。

对于像这样的应用程序,通过使用类似这样的东西,非递归地执行它会好得多:

ReversePrint(YourList l) {
    Node n = l.last;
    while (n != null) {
        System.out.println(n.data);
        n = n.prev;
    }
}

请注意,完成此类操作需要一些其他功能。列表必须是双向链接,包括向前和向后,并且必须有某种类型的YourList类来封装它(为简单起见)。