在不更改原始

时间:2017-02-14 07:17:03

标签: java linked-list pass-by-reference

我试图反转一个有效的链接列表,但是当我尝试打印原始时,它会失败(只打印头部)。我的问题是,为什么倒车会影响原件。以下是我的代码。 LinkedList是我自己的类,Node也是。在倒车之前,如果我尝试打印我的列表,那就可以了。

public static void main(String[] args) {
    LinkedList list;
    ...
    Node head = list.getHead();
    Node rev = reverse(head);
    Node temp = rev;
    while (temp != null) {
        System.out.println(temp);
        temp = temp.next;
    }

    temp = head;
    while (temp != null) {
        System.out.println(temp);
        temp = temp.next;
    }
}

private static reverse(Node head) {
     // Reversing the linked list
}

EDIT :: 这似乎是一件Java事情。 Java通过引用传递对象。当我将head作为参数传递时,它通过引用传递,对它的任何更改都会反映在调用函数中。 做节点h = head然后传递h作为参数将不起作用,因为h将是与head相同的对象。 我能想到的唯一选择是创建一个新对象,复制链表并将其作为参数传递。

我的问题是,有更好的解决方案吗?

2 个答案:

答案 0 :(得分:2)

要理解它,请将您的列表看作是这样的

list (list.head =a) --> a (a.next=b) --> b (b.next= c) -> c (c.next = null)

如果你得到了头,那么你就得到了对象'a'。 然后你正在修改对象'a'。 所以你可以看到你正在编辑列表。

您需要做的是:   抓住头脑   创建一个副本   反转副本   获取下一个项目   复制它   扭转它   加入到最后   等等

由于您使用自己的类而不是Java集合类,因此最简单的方法是确保reverseNode()仅编辑您传递它的副本,并返回副本。 首先确保你的Node类有一个复制另一个Node的构造函数,然后做这样的事情:

private static Node reverse(Node original) 
{
  Node retval = new Node(original);
  // or you could use clone () as Bhavik suggested, if your Node class implements it
  // modify retval 
  // I haven't shown code to reverse it as I assume you already have that and you didnt specify if it was a bidirectional list or just one direction.

  return retval;
}

或者您可以在Node类中添加一个静态方法来构造一个颠倒的新节点:

static Node createReverse(Node n) 
{
    return new Node(n.data,n.next,n.prior);
}

或者是节点类的非静态方法,它返回自身的反向副本;

Node createReverse()
{
   return new Node(this.data,this.next,this.prior);
}

但你应该认为这会变得非常难看,因为你的副本仍会有指向现有列表的指针!

更好的技巧可能是创建一个新的空列表,然后从原始列表开始,制作副本,并将其添加到新列表的开头。

您可以使用递归来执行此操作,但可能很容易耗尽内存。

但是,不是手动执行此操作,您可以查看java.util包并切换到使用其LinkedList和列表项类型之一。这些课程已经解决了所有这些问题。

然后你可以(如果你需要保持原始列表不被修改):    - 复制整个清单。    - 反转副本如下

如果您不关心保留原件,请在列表中使用此方法(下方),然后无需复印。

来自java.util.Collections:

Collections.reverse(List a_list);

Collections类将选择一种有效的方法来反转列表,具体取决于它是双向的,单向的等等。

答案 1 :(得分:0)

Chunko的答案是正确的,因为您应该创建节点的副本,而不是仅仅传递对它们的引用。
但是,我认为你可能会过度思考这个:

LinkedList reversedList = new LinkedList();
for (int i = originalList.size()-1; i >= 0; i--) {
    reversedList.add(list.get(i));
}

Java的LinkedList没有getHead()方法,所以我猜你正在使用链接列表的一些与作业相关的自定义实现。不过,您的实施应该有一个add()方法,可以将新的Node附加到列表中,还有一个get(int)方法可以返回给定位置的项目。
您可以使用这些方法创建新列表,并使用相反顺序的原始列表项填充它。