双向链表删除第一次出现的方法

时间:2015-02-02 01:12:50

标签: java linked-list

有人能帮我为这个双向链表编写removeFirstOccurrence方法吗?

删除第一次出现目标数据的节点。搜索从头开始。如果目标数据不在列表中,则列表保持不变。最后一个节点的下一个字段的值为null。没有尾部参考。

public class DoublyLinkedList {

    protected Node head; // Note there is no tail reference.
    public void addToFront(String data) {
        head = new Node(data, head, null);
        if(head.next != null) {
            head.next.previous = head;
        }

    public void removeFirstOccurrence(String data) { 
    }

    protected class Node {
        protected String data;
        protected Node next;
        protected Node previous;
        private Node(String data, Node next, Node previous) {
            this.data = data;
            this.next = next;
            this.previous = previous;
        }
        private Node(String data) {
            this(data, null, null);
        }
    } // end of Node class 
} // end of DoublyLinkedList class

到目前为止,我写了类似这样的内容,但是当删除列表中没有的字符串时,我得到一个空指针异常。我已经标明了NPE的发生地点。如果你可以帮助弄清楚为什么或者如果你有一个完全不同的方法,那就好了,请告诉我,谢谢!

public void removeFirstOccurance(String data) {
    if (data.equals(null)) {
        throw new java.lang.IllegalArgumentException("Data is null");
    }
    if (head == null) {
        throw new java.util.NoSuchElementException("List is empty");
    }

    Node current = head;
    if (current.data.equals(data)) {
        head = current.next;
    } else {
        boolean found = false; //keeps track if we found the element
        while (current != null && !found) {
            if (current.next.previous == null) { //NPE here
                current.next.previous = current;
            }
            current = current.next;
            if (current.data.equals(data)) {
                found = true;
                if (current.next == null) {
                    current.previous.next = null;
                } else {
                    current.previous.next = current.next;
                }
            }
        }
    }
}

3 个答案:

答案 0 :(得分:0)

在访问其值之前,您没有在循环中测试current.next。 因此,当到达列表末尾时,会发生异常。

while (current != null && !found) { // testing current
    if (current.next.previous == null) { // accessing current.next + testing current.next.previous
        current.next.previous = current;
    }
    // your loop
}

注意:看起来像工作分配,所以我不会发布代码。

答案 1 :(得分:0)

这将是我帮助您找到错误的原因。在评估current.next.previous时会发生空指针异常。您之前的行确保current != null。因此current.next可能是空值。一种简单的方法是在使用该值之前添加assert current.next != null。如果这个理论是正确的,那么就会抛出断言异常。然后,您可以开始检查其他代码,以找出此时current.next可能为空的原因。

作为编程提示,我建议您使用{em>批次的assert语句。从长远来看,它们可以为您节省很多痛苦。对于其他人来说,阅读代码时,他们也是一个很好的提示,关于你假设的每个条件都是正确的。

答案 2 :(得分:0)

只是一些提示,因为我甚至没有在这台机器上安装Java来检查代码。

我建议你专注于你必须做的事情:找到第一次出现。然后,一旦找到它:更新前一节点和后一节点的指针

E.g。在我看来,当您检查数据是否在第一个节点时,您忘记更新current.previous current.next指针。这样你就不会真正删除节点..

所以,我的方法是拥有像

这样的东西
while(!current.data.equals(data) && current.next != null){
    current = current.next; // looking through the list
}

然后,仔细检查您是否未到达列表末尾,更新指针以便

current.previous.next = current.next;
current.next.previous = current.previous;

另请注意,如果只是为了复制值,则不需要将null视为特殊内容。 我的意思是在你的最后一个if:

if (current.data.equals(data)) {
                found = true;
                if (current.next == null) {
                    current.previous.next = null;
                } else {
                    current.previous.next = current.next;
                }
            }

您只需指定current.previous.next = current.next;

即可

希望有所帮助。