Java中的反向LinkedList

Java中的反向LinkedList,java,collections,Java,Collections,我正在这篇文章中寻找解决方案 我复制了下面的一个解决方案。我已经实现了它,效果很好 public ListNode Reverse(ListNode list) { if (list == null) return null; // first question if (list.next == null) return list; // second question // third question - in Lisp this is easy, but we

我正在这篇文章中寻找解决方案

我复制了下面的一个解决方案。我已经实现了它,效果很好

public ListNode Reverse(ListNode list)
{
    if (list == null) return null; // first question

    if (list.next == null) return list; // second question

    // third question - in Lisp this is easy, but we don't have cons
    // so we grab the second element (which will be the last after we reverse it)

    ListNode secondElem = list.next;

    // bug fix - need to unlink list from the rest or you will get a cycle
    list.next = null;

    // then we reverse everything from the second element on
    ListNode reverseRest = Reverse(secondElem);

    // then we join the two lists
    secondElem.Next = list;

    return reverseRest;
}
然而,我不明白的是最后几行

secondElem.next = list;
return reverseRest;

看来我们根本就不退第二个元素了?但是我调试了代码,看起来secondElem已经在reverseRest中了。这是因为它在Java中是按值引用的,并且在应用
secondElem.Next=list
时会自动更新吗?

如果您的目标是简单地反转列表,请使用不要考虑传递语义,请考虑内存中的对象和包含对它们的引用的变量

初始状态:

(list)
   |
   V
[  1  ] -> [  2  ] -> ... -> [  N  ]
(list)   (secondElem)
   |          |
   V          V
[  1  ]    [  2  ] -> ... -> [  N  ]
(list)   (secondElem)      (reverseRest)
   |          |                 |
   V          V                 V
[  1  ]    [  2  ] <- ... <- [  N  ]
(list)   (secondElem)      (reverseRest)
   |          |                 |
   V          V                 V
[  1  ] <- [  2  ] <- ... <- [  N  ]
list.next=null后的

(list)
   |
   V
[  1  ] -> [  2  ] -> ... -> [  N  ]
(list)   (secondElem)
   |          |
   V          V
[  1  ]    [  2  ] -> ... -> [  N  ]
(list)   (secondElem)      (reverseRest)
   |          |                 |
   V          V                 V
[  1  ]    [  2  ] <- ... <- [  N  ]
(list)   (secondElem)      (reverseRest)
   |          |                 |
   V          V                 V
[  1  ] <- [  2  ] <- ... <- [  N  ]
递归调用后:

(list)
   |
   V
[  1  ] -> [  2  ] -> ... -> [  N  ]
(list)   (secondElem)
   |          |
   V          V
[  1  ]    [  2  ] -> ... -> [  N  ]
(list)   (secondElem)      (reverseRest)
   |          |                 |
   V          V                 V
[  1  ]    [  2  ] <- ... <- [  N  ]
(list)   (secondElem)      (reverseRest)
   |          |                 |
   V          V                 V
[  1  ] <- [  2  ] <- ... <- [  N  ]
然而,我不明白的是最后几行

secondElem.next = list;
return reverseRest;
secondElem.next=列表
返回反向测试

让我逐一向您解释您不理解的两行内容:

1.secondElem.next = list;
我认为secondElem的创建增加了复杂性。根本不需要变量secondElem

与此相反:

    // then we reverse everything from the second element on
    ListNode reverseRest = Reverse(secondElem);

    // then we join the two lists
    secondElem.Next = list;
使用以下命令:

ListNode reverseRest = Reverse(list.next);    
list.next.next = list;
它更容易掌握。最后一行代码清楚地显示了列表反转过程本身

2. return reverseRest;

查看reverseRest变量的用法并理解其用途。它的唯一目的是将列表的原始尾部的值过滤到所有递归调用的末尾,这样我们就可以将原始尾部(也是新的头部)返回给调用反向函数的主函数。您必须理解,在递归调用之间,我们根本没有更改变量reversereest的值——无论我们从Reverse(secondElem)收到什么作为返回值,我们都是从函数返回“原样”的值,从而快速实现这一点

更好的方法是使用
DegendingIterator()
。这取决于他是想“永久”反转列表,还是只想以相反的顺序进行迭代。