【问题标题】:doubly linked list remove first occurrence method双向链表删除第一次出现的方法
【发布时间】:2015-02-02 01:12:49
【问题描述】:

谁能帮我为这个双向链表写一个 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;
                }
            }
        }
    }
}

【问题讨论】:

    标签: java linked-list


    【解决方案1】:

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

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

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

    所以,我的方法是有类似的东西

    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 (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;

    希望有所帮助。

    【讨论】:

      【解决方案2】:

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

      作为编程技巧,我建议您使用 大量 assert 语句。从长远来看,它们将为您节省很多痛苦。对于阅读代码的其他人来说,它们也是很好的提示,可以帮助您了解您假设的条件在每个点上都是正确的。

      【讨论】:

      • @Hartok 我不同意。断言并不打算影响功能(它们在功能上不做任何事情)。它们旨在确保代码的正确性和可维护性。在我看来,它们几乎(但不完全)与综合单元测试一样重要。
      • 我明白你的意思,我们在测试类中使用 Assert 来测试以确保一切正常,但就我正在编辑的此类添加断言而言,它在列表中我不允许使用的代码,以及无法使用的代码 - 继续;等
      【解决方案3】:

      在访问其值之前,您没有在循环中测试 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
      }
      

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

      【讨论】:

      • 如果我添加一个 while 循环说 while(current.next != null) 那么它会在它结束时停止吗?我已经在检查上面的 current != null 并且我认为这就是我所需要的,但也许它应该是 current.next?
      • 更新了我的答案。你可以做一些测试,看看它是否有效。
      猜你喜欢
      • 1970-01-01
      • 2012-03-23
      • 1970-01-01
      • 1970-01-01
      • 2014-06-02
      • 2014-10-13
      • 2023-03-25
      • 2016-06-10
      • 1970-01-01
      相关资源
      最近更新 更多