为java项目创建了一个链表类,需要一个方法来反转列表,这样我和我的朋友最终想出了以下递归方法及它的帮助方法:
(只是为了澄清,first
是列表中第一个节点的实例变量)
public void reverse()
{
first = reverse(first);
}
public Node reverse(Node in)
{
if (in == null || in.next == null)
{
return in;
}
Node next = in.next;
in.next = null;
Node rest = reverse(next);
next.next = in;
return rest;
}
当节点包含整数并且我们在列表的开头输入1,2和3时(当添加为第一个节点时它们变为3,2,1)然后尝试将3,2,1转换为成为1,2,3,该功能按计划运行。
我的问题是,我真的无法理解这里发生的事情。
例如,当我跟踪函数(3,2,1)时,它显示为:
next
= in.next
(2, 1
)再次传递,直到它只是(1)
,然后再传递回rest
。但是在递归发生之后,rest
实际上没有发生任何事情。它发生在next.next
,我无法以任何方式弄明next.next
对rest
的影响。
在冒泡回来期间,我无法找到rest
从(1)
变为(1,2)
到(1,2,3)
的点。
如果有人能够更深入地解释这个函数如何修改rest
那将是很好的。我已经追踪了这个函数差不多20次,现在试图理解并且正在发生一些我似乎无法看到的事情。
我甚至把它带给了我的老师,他给了我一些相当于&#34的BS响应;如果它有效,那么它有效,它的递归,不要试图理解它。&# 34; - 那是什么建议?
谢谢
答案 0 :(得分:1)
尝试绘制一个包含2个节点的列表。这是最简单的例子。
first --> [A] -> [B] -> null
我们调用reverse(first)
,由于A
不为null,我们会产生以下分配:
in = A
next = B
我们在此步骤中打破了A和B之间的联系:
in.next = null;
所以,我们有:
first --> [A] [B] -> null
现在我们想要其余的,它被分配给这个函数的递归调用,而不是B。我们现在用B重复这些步骤,但由于B.next
为空,我们只剩下B。
因此,我们将{B}作为rest
的结果返回。我们现在将next.next
分配给in
,这意味着B.next
现在是A
。
[B] -> [A] -> null
^
first
我们将rest
返回给任何调用它的人,在这种情况下,会导致first
的分配。
first --> [B] -> [A] -> null
......现在,列表正好相反。
这是它的一般细分;看看它有三个节点,你会看到更多的行为。请记住:每次递归调用都会为in
和next
创建新变量,之前存在的变量将被保留,直到我们从此特定方法返回。