【问题标题】:Java Linked List ProblemsJava 链表问题
【发布时间】:2015-09-29 03:09:49
【问题描述】:

我有两个难以理解的练习题。对于#1,答案是列表是反向打印的,有人可以向我解释一下吗?还有#7,为什么列表一旦到达空值就会开始倒退?如果有人能提供一些快速的解释,将不胜感激,谢谢!

1) 如果我们用头节点调用给定的链表,下面的函数会做什么?

void method1(Node<T> node) {
  if(node == null)
    return;

  method1(node.getNext());
  System.out.println(node.getData().toString());
}

一个。打印链表的节点。

b.以相反的顺序打印链表的节点。

c。打印链表的备用节点。

d。以相反的顺序打印备用节点。

回答

b.以相反的顺序打印链表的节点。

7) 如果我们用链表 1 → 2 → 3 → 4 → 5 → 6 的头节点调用它,这个方法会打印什么?

void method1(Node<Integer> node) {
  if (node == null)
    return;
  System.out.printf(“%d ”, node.getData());

  if (node.getNext() != null)
    method1(node.getNext().getNext());
  System.out.printf(“%d ”, node.getData());
}

一个。 1 6 2 5 3 4

b. 1 3 5 6 4 2

c。 1 3 5 1 3 5

d。 1 3 5 5 3 1

回答

c。 1 3 5 5 3 1

【问题讨论】:

  • 理解此类问题的最佳方法是编写代码并使用调试器逐步执行。第一个问题是递归的,System.out.println(...) 在方法返回之前被调用。试着想想程序对于给定的输入列表将采取的步骤顺序。

标签: java linked-list nodes


【解决方案1】:

问题一:

这是一个递归方法调用,这意味着它会不断地调用自己,直到满足中断条件(在这种情况下,没有下一个节点可以移动)。所以,让我们一行一行地走一遍。

void method1(Node<T> node) {
    if(node == null) // ends the recursive calls without doing anything extra
        return;

    method1(node.getNext()); // Do something with the next node before this node
    System.out.println(node.getData().toString()); // Print contents of current node.
}

如您所见,我们第一次实际打印任何内容是在我们位于链表的末尾时(当node.next() 返回 null 时)。在第一次打印之后,调用在堆栈中向上移动(因此在列表中向后移动),同时打印每个节点的内容。

问题2:

这与问题 1 几乎相同,只是加入了一些曲折。首先,我们在递归调用之前 打印当前节点的内容。所以实际上,我们将按顺序打印每个节点的内容,然后以相反的顺序打印。稍微令人困惑的部分是我们在每个节点上调用method1,但在每个其他节点上,这意味着我们每次调用它时都会跳过一个节点。

所以总结这个问题的答案,我们有效地打印当前节点的内容,跳过一个,打印下一个节点的内容,等等......直到我们到达可用节点的末尾,然后我们只是回溯并再次打印所有内容(只是这次以相反的顺序)。

【讨论】:

    【解决方案2】:

    如果你画出调用堆栈,这些都更容易可视化。这些指令是按顺序执行的,所以我发现像这样可视化调用序列和调用堆栈深度很有帮助:

    问题 1:

    List = 1 → 2 → 3 → 4 → 5 → 6
    method1(1)
      method1(2)
        method1(3)
          method1(4)
            method1(5)
              method1(6)
                method(null)
                  return
                println(6)
              println(5)
            println(4)
          println(3)
        println(2)
      println(1)
    

    这里的调用顺序可以从上到下看到。在打印任何内容之前调用method1。一旦method1 遇到基本情况,它就会返回到上一个调用,在这种情况下是method1(6) 调用。

    这里的每个缩进都是另一个recursive 调用,有助于可视化call stack。有很多非常好的答案比我能更好地解释递归(比如programmers.stackexchange.com 上的这个)。

    问题 7:

    你可以对这个问题做同样的事情:

    1 → 2 → 3 → 4 → 5 → 6
    method1(1)
      printf("%f ", 1)
      method1(3) // node.getNext().getNext() = 1 → 2 → 3
        printf("%f ", 3)
        method1(5)
          printf("%f ", 5)
          method1(null) // node.getNext().getNext() = 5 → 6
            return
          printf("%f ", 5)
        printf("%f ", 3)
      printf("%f ", 1)
    

    【讨论】:

      猜你喜欢
      • 2018-05-05
      • 2012-07-29
      • 1970-01-01
      • 2021-05-03
      • 2021-01-13
      相关资源
      最近更新 更多