繁体   English   中英

迭代链表时出现NullPointerException

[英]NullPointerException when iterating over linked list

代码背后的概念是删除列表中大于之前元素的元素。 在这种情况下,我的节点有一个int数据,并且可以通过它进行比较。 (这些类在扩展Comparable <>

问题是,当此代码与链表一起运行时,我得到nullpointexception:

 [2,5,4,3,7,6,4,2,3,4,5] 

应该获得的预期列表是

[2,2]

因为(5> 2)删除5然后(4> 2)删除4然后(3> 2)删除3 ...依此类推,直到它以nullpointerexception结束。

另一个例子是列表

[3,1,-2,3,6,-1,3,2,1]

该名单应该最终成为

[3,1,-2]

其中的调试代码用于显示删除了哪些元素。

getter方法是基础并且工作正常。

public void deleteIncrementing() {
    T largest = null;

    while(head.getNext() != null || head != null) {
        Node<T> temp = head.getNext();

        while(temp.getValue().compareTo(head.getValue()) > 0){
            largest = temp.getValue();
            remove(largest);
            System.out.println(largest); // debug
            if(temp.getNext() == null){
                break;
            }
            temp = head.getNext();
        }
        head = temp;
    }
}

来自建议的伪代码:

    Node<T> current = head;
    Node<T> previous = null;

    while(current != null) {
        if (previous != null){
            if (current.getValue().compareTo(previous.getValue()) > 0){
                //System.out.println(current.getValue().toString());
                remove(current.getValue());
            }
            if (current.getValue().compareTo(previous.getValue()) < 0){
                //System.out.println(previous.getPrevious().getValue().toString());
                //System.out.println(current.getValue().toString());
                remove(previous.getValue());
            }
        }

        previous = current;
        current  = current.getNext(); 
    }

哪个仍然不正确,因为它没有考虑到倒数第一个元素并保留最后一个元素...任何原因?

首先,这个条件:

while (head.getNext() != null || head != null)

应该:

while (head != null && head.getNext() != null)

经常检查空第一

我不知道这是否是您的原因,但是您必须在while循环中切换测试:

while (head != null && head.getNext() != null)

当你第一次测试head.getNext() != null并且head为null时,将抛出NullPointerException

有关更多信息,请查看此处

你过度思考这个问题。

考虑一下您需要完成的任务:编写一个函数来删除其值大于前一个元素的LinkedList元素。

阅读本声明之后,您应该知道在LinkedList的每个点(例如当前元素和前一个元素)需要考虑的内容。 因此,实际上不需要嵌套的while循环。

伪代码:

current  = head 
previous = null

while current is not null
   is previous non-null and current > previous?
      if yes: delete current
      if  no: do nothing

   previous = current
   current  = current.next 

看看你是否可以使用这个伪代码来简化你自己的代码。

除了别人提到的不正确的head检查外,我认为这有一些潜在的问题:

    while(temp.getValue().compareTo(head.getValue()) > 0){
        largest = temp.getValue();
        remove(largest);
        System.out.println(largest); // debug
        if(temp.getNext() == null){
            break;
        }
        temp = head.getNext();
    }
    head = temp;

temp将引用即将被删除的节点。 该节点会发生什么? 我不知道,因为我不知道这是什么列表类型或remove什么。 但是,除非列表类的文档清楚地说remove不会影响节点的“下一个”指针,否则我不会指望它。 作为一般规则,应 remove调用之前保存这种数据。 (在其他语言中,您可能有一个“删除”也明确释放存储空间,肯定有必要先保存链接。)

更严重的问题是,即使“下一个”指针保持不变,列表末尾会发生什么。 temp指向随后被删除的节点。 它的“下一个”指针为null ,所以你打破了。 但是你设置head = temp ,这意味着head现在指向一个不再在列表中的节点。 我认为只有当你达到那个点时才想要head = temp ,因为compareTo如果你到达那里因为你到达了列表的末尾。

暂无
暂无

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

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