繁体   English   中英

这个Java代码如何工作? 从未排序的链接列表中删除重复项

[英]How this Java code works? Remove duplicates from an unsorted linked list

我有一个LinkedList节点类:

public static class Node {
    int value;
    Node next;

    Node(int value){
        this.value = value;
        this.next = null;
    }
}

而删除重复方法:

public static void deleteDups(Node n) {
    Hashtable<Integer, Boolean> table = new Hashtable<Integer, Boolean>();
    Node previous = null;
    while (n != null) {
        if (table.containsKey(n.value)) previous.next = n.next;
        else {
            table.put(n.value, true);
            previous = n;
        }
        n = n.next;
    }
    }

public static void printList(Node list) {
    Node currentNode = list;
    while(currentNode != null) {
        System.out.print(currentNode.value + ", ");
        currentNode = currentNode.next;
    }
    System.out.println("");

}

有用。 但是怎么样? 在方法中,我删除列表n,最后n为空。 但为什么它在这里不为空:

Node list = new Node(5);
list.next = new Node(2);
list.next.next = new Node(3);
list.next.next.next = new Node(2);
list.next.next.next.next = new Node(1);
list.next.next.next.next.next = new Node(3);

printList(list);    
deleteDups(list);
printList(list);

输出:

5, 2, 3, 2, 1, 3
5, 2, 3, 1

我错过了什么?

如果我打印n和之前:

  public static void deleteDups(Node n) {
    Hashtable<Integer, Boolean> table = new Hashtable<Integer, Boolean>();
    Node previous = null;
    while (n != null) {
        if (table.containsKey(n.value)) previous.next = n.next;
        else {
            table.put(n.value, true);
            previous = n;
        }
        n = n.next;

        System.out.println("");
        System.out.println("");
        System.out.print("previous is ");
        printList(previous);            
        System.out.print("n is ");
        printList(n);
    }
    }

输出是:

previous is 5, 2, 3, 2, 1, 3, 
n is 2, 3, 2, 1, 3, 


previous is 2, 3, 2, 1, 3, 
n is 3, 2, 1, 3, 


previous is 3, 2, 1, 3, 
n is 2, 1, 3, 


previous is 3, 1, 3, 
n is 1, 3, 


previous is 1, 3, 
n is 3, 


previous is 1, 
n is 

最后n和前一个是空的! 怎么样呢?

简单地说它迭代链表并记住它遇到的每个值。 如果它遇到一个值,它已经看到它通过将前一个节点(在复制之前遇到的节点)与下一个节点(复制节点之后的节点)连接起来,中断了链中的重复条目。

想象一下,它就像从链条中取出链接一样。

整个算法就地工作,因此之后不需要重新创建列表。 你只需丢弃不再需要的节点。

这有点危险,因为仍然可以引用不再是过滤链表的一部分的节点。 以某种方式使它们无效会更好。

在另一方面,节点next属性将总是导致无论是过滤的链表(n步之后)的节点是否仍然存在列表中的某个值的算法还不看或null ,如果重复的节点是在已经链接列表的结尾。 然而, next节点仍然会有重复,直到它到达一个节点,该节点再次成为重复的自由链表的一部分但是可以改变算法,这样即使这样也不会发生。

编辑以回答为什么printList最后没有打印/ null

这是因为此时n不再是您的起始节点,它始终是“下一个”节点。 所以最后n实际上是“null”,因为“null”是最后一个节点之后的元素。 你必须保留你的起始节点n(你传递给deleteDups方法的节点),因为这个节点描述了你过滤列表的起始节点。你的printList方法只打印你传递给它的节点之后的所有下一个节点。所以发生的最后一次调用是你的printList(前一个)(这包含最后一个元素)和printList(n)什么也不做,因为n在那一点上是“null”。

只是尝试创建节点的链接列表。 然后将第一个Node传递给deleteDups,然后使用传入其中的Node调用printList。

 Node start = new Node(...);

 //Initialize and connect more nodes consecutively here

 printList(start); //unfiltered List will be printed     
 deleteDups(start);
 printList(start); //filtered List will be printed, all duplicates have been unhinged from your linked list

该列表是“重新创建的”: previous.next = n.next; 更改节点,并通过此操作删除要跳过的项目

2 --> 3 --> 2
previous.next = n.next;
2 --------> 2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM