反向列表实现和指针理解

时间:2017-07-15 21:29:13

标签: java pointers nodes

假设我有一个名为Node的类:

public class Node {
    public Node next; 

    //etc......
}   

和一个类NodesList:

public class NodesList {
    public Node head;

    //etc.... 
}   

现在我想实现一个反转列表的函数,如:

public reverseList () {
    Node curr = head; 
    Node prev = null;

    while (curr != null){
       curr.next = prev;
       prev = curr;
       head = head.next;
       curr = head;
    }

    head = prev;
 }

我的问题非常基本:我分配了 curr = head

为什么,在作业 curr.next = prev, 中,它不会将更改为 head.next = prev 并破坏列表?

我在哪里可以阅读它以了解更多幕后发生的事情?

非常感谢!!!

3 个答案:

答案 0 :(得分:4)

currhead最初指向第一个节点。当您执行curr.next = prev时,curr.nexthead.next都是null。由于第一个节点与列表其余部分之间的连接丢失,因此您无法立即反转列表。现在,当head = head.next语句执行时,您的head将指向null,这意味着列表没有起始点。

要记住的一件事是永远不要使用head指针移动列表中的节点。应该head始终指向列表的开头。在反转列表的情况下,可以更新head以在反转后指向列表的新起始节点。

反转列表的一种方法是:

Node prev = null;
Node curr = head;
Node next;

while (curr != NULL)
{
    next  = curr.next;  
    curr.next = prev;   
    prev = current;
    current = next;
}
head = prev;

在上面的代码片段中,有一个名为next的指针,它首先指向current的下一个节点。所以现在执行curr.next = prev之后,curr可以通过语句curr = next移动到列表中的下一个节点。这可确保列表的连接不会丢失。

while循环反转列表后,prev将指向列表的新第一个节点。现在,您可以修改head以指向此节点。

答案 1 :(得分:0)

  

为什么在作业curr.next = prev中,它还没有将head更改为head.next = prev并破坏列表?

但确实将head.next更改为prev。在赋值时,currhead是对同一对象的引用。这不会破坏列表,因为head在循环运行时被设置为其他元素。

如果这听起来有点令人困惑,请继续阅读。

  

我在哪里可以阅读它以了解更多幕后发生的事情?

幕后没有任何事情发生,你只需要在场景之前正确看待发生的事情"。

发生的事情是您正在使用旧列表的相同节点构建反向列表。现在,你正在以唯一的方式遍历旧列表,这是前进的 - 从旧列表的头部到尾部,通过.next前进。但是对于新列表,这需要是列表的末尾,所以每当你看到另一个元素时,你在头之前添加它而不是在尾之后添加 >你的建设清单。

所以如果你有:

(head) -> [node 1] -> [node 2] -> [node 3]

您正在将其转换为:

null <- [node 1] <- (head)                        [node 2] -> [node 3] -> null

null <- [node 1] <- [node 2] <- (head)            [node 3] -> null

null <- [node 1] <- [node 2] <- [node 3] <- (head)

答案 2 :(得分:0)

不是推理什么指向什么,而是推理弹出和推送操作要简单得多。在伪代码中,您可以将lst反转到rvs,如下所示:

rvs = null;
while (lst != null) {
  Node tmp = pop(lst);
  rvs = push(rvs, tmp);
}
// rvs now contains the reversed list

现在我们需要做的就是将poppush替换为其实现:

rvs = null;
while (lst != null) {
  // pop from lst
  Node tmp = lst;
  lst = lst.next;
  // push onto rvs
  tmp.next = rvs;
  rvs = tmp;
}