【问题标题】:Java: Deleting node from linked listJava:从链表中删除节点
【发布时间】:2018-07-29 16:23:50
【问题描述】:

我正在尝试在 java 中删除链表中的一个节点,但在尝试使用我的 deletenode() 方法时,我不断收到 NullPointerException。

I get the following error trace:
Exception in thread "main" java.lang.NullPointerException
at linkedlist.LinkedList.deletenode(LinkedList.java:44)
at linkedlist.LinkedList.main(LinkedList.java:69)
/Users/carsongedeus/Library/Caches/NetBeans/8.2/executor-snippets/run.xml:53: 
Java returned: 1
BUILD FAILED (total time: 3 seconds)


package linkedlist;

import java.util.Scanner;

/**
 *
 * @author carsongedeus
 */

class Node {

    int data;
    Node next;

    Node(int data) {
        this.data = data;
    }
}

public class LinkedList {

    Node head;
    Node temp;

插入到列表的头部。

    public Node insertnode(int data) {

        if(head == null) {
            head = new Node(data);
        } else {
            temp = new Node(data);
            temp.next = head;
            head = temp;
        }
        return head;
    }

Delete 方法在用户在链表的节点内键入指定整数后给出 NULLPointerException。

    public void deletenode(int data) {

        Node trace;
        Node del;

        for(trace = head; trace != null; trace = trace.next) {

            if(trace.next.data == data) {
                del = trace.next;
                trace = trace.next.next;
                del.next = null;
            }
        }
    }

打印机

    public void printer() {
        System.out.println(head.data);
    }

    public static void main(String[] args) {

        LinkedList linkedlist = new LinkedList();
        Scanner scan = new Scanner(System.in);
        int n;

        for(int i = 0; i < (n = (int)(Math.random()*100+1)); i++) {
            linkedlist.insertnode((int)(Math.random()*100+1));
            linkedlist.printer();
        }

        System.out.println("Delete something: ");
        int input = scan.nextInt();
        linkedlist.deletenode(input);

        for(int j = 0; j < n; j++) {
            linkedlist.printer();
        }
    }
}

【问题讨论】:

  • 你能上传你的错误跟踪吗?
  • 如果 head = null(列表中没有节点)或列表中有一个节点,则您的删除节点方法将具有 npe。应该检查当前元素 trace.data == data not trace.next.data == data
  • trace.data==data替换trace.next.data==data

标签: java linked-list java.util.scanner nodes singly-linked-list


【解决方案1】:
public void deletenode(int data) {
    if (head != null && head.data == data) {
        head = head.next; // delete head
        return;
    }
    Node prev = null;
    Node cur = head;
    while (cur != null && cur.data != data) {
        prev = cur;
        cur = cur.next;
    }
    prev.next = cur.next; // delete cur
}

【讨论】:

    【解决方案2】:

    在您的方法中,要删除的节点是trace.next(您将其称为del)。这意味着tracenext 指针需要更新为trace.next.next,有效地“跳过”要删除的节点(trace.next)。这看起来像:trace.next = trace.next.next

    您正在做的是修改trace 本身,将其设置为trace.next.next。我知道这是为了使迭代正常工作,但会弄乱您的其余代码,因为您丢失了指向需要更新的节点的指针。如果我们修改trace.next,循环将在结束运行trace = trace.next 时负责正确推进指针。

    在没有更多指向它的引用的 Java 对象中,从计算机的内存中删除——这个过程称为垃圾收集。由于此时我们已经修改了trace.next,因此没有对要删除的节点的进一步引用,除了您创建的del 变量。一旦该变量在此函数结束时超出范围,该节点将被垃圾收集,您无需采取进一步行动。您甚至根本不需要 del 变量。一旦我们通过更新(跳过)旧的trace.next 失去了对它的引用,就不再存在对该节点的引用,垃圾收集器就会剔除它。

    考虑到所有这些,您的代码就变成了:

    public void deletenode(int data) {
    
        Node trace;
    
        for(trace = head; trace != null; trace = trace.next) {
    
            if(trace.next.data == data) {
                trace.next = trace.next.next;
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      不要声明临时字段:改用局部变量:

      public Node insertnode(int data) {
      
          if(head == null) {
              head = new Node(data);
          } else {
              Node temp = new Node(data);
              temp.next = head;
              head = temp;
          }
          return head;
      }
      

      为了回答您的问题,您测试 trace 是否不为空,然后尝试访问 trace.next.data 而不测试 trace.next。

      试试这样的:

      public void deletenode(int data) {
      
          Node prev = null;
      
          for(Node trace = head; trace != null; trace = trace.next) {
      
              if(trace.data == data) {
                  if (prev == null) {
                      head = trace.next;
                  } else {
                      prev.next = trace.next;
                  }
              } else {
                  prev = trace;
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        我认为您解决问题的方法是错误的。请找到处理链表问题的适当方式。

        LinkedListNode 类:

        class LinkedListNode {
            int data;
            LinkedListNode next;
            LinkedListNode(int data) {
                this.data= data;
                this.next=null;
            }
        }
        

        开头插入:

         LinkedListNode insertNodeAtBegining(LinkedListNode head, int val) {
                LinkedListNode temp= head;
                head= new LinkedListNode(val);
                head.next=temp;
                return head;
            }
        

        删除节点:

        LinkedListNode deleteNode(LinkedListNode head, LinkedListNode node) {
            if(head==null) {
                return head;
            }
            if(head.data==node.data) {
                return head.next;
            }
        
            LinkedListNode temp=head;
            while(temp.next!=null) {
                if(temp.next.data==node.data) {
                    temp.next=temp.next.next;
                }
                temp=temp.next;
            }
            return head;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-01-01
          • 1970-01-01
          • 2013-01-08
          • 1970-01-01
          • 2018-08-30
          • 2012-11-06
          相关资源
          最近更新 更多