编程语言
首页 > 编程语言> > 此Java代码如何工作?从未排序的链接列表中删除重复项

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

作者:互联网

我有一个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和previous为空!那怎么运作呢?

解决方法:

简单地说,它会迭代链接列表并记住它遇到的每个值.如果遇到一个已经知道的值,它将通过连接上一个节点(在复制之前遇到的一个节点)和下一个节点(在复制之后的一个节点)来断开链中的重复条目.

试想一下,就像断开链接一样.

整个算法在原位运行,因此以后无需重新创建列表.您只是丢弃了不再需要的节点.

这有点危险,因为仍然有对Node的引用,这些Node不再是过滤后的链接列表的一部分.最好以某种方式使它们无效.

另一方面,如果列表中仍然存在算法尚未看到的值,则节点的next属性将始终导致已过滤链表的节点(在n个步骤之后),或者如果重复的节点位于列表中,则为null.链表的末尾.尽管如此,下一个节点仍将具有重复项,直到它再次到达重复的自由链接列表中的一个节点为止,但是可以更改算法,因此即使这种情况也不会发生.

编辑以回答为什么printList在末尾什么也不打印的结果:

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

只需尝试创建节点的链表即可.然后将第一个节点传递到deleteDups中,然后将传递给它的节点调用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

标签:linked-list,java
来源: https://codeday.me/bug/20191119/2037035.html