实施单一链接列表

时间:2015-04-18 07:05:11

标签: java

我正在尝试学习数据结构,但我遇到了可怕的NullPointerException,我不知道如何修复它。

我的SinglyLinkedList<E>类实现了一个界面LinkedList,我重新定义了一些方法,例如add(), get(), contains()等。

使用NullPointerException方法时会发生clear()。它指向removeLast()下的方法nodeBefore.setNext(null)。它还指向clear()下的remove(head.getElement())方法。

此外,如果我的代码中有任何可以改进的内容,请告诉我。

public class SinglyLinkedList<E> implements LinkedList<E> {

    private class Node<E> {

        public Node<E> next;
        public E element;

        public Node(E element) {

            this.element = element;
        }

        public Node (E element, Node<E> next) {

            this.element = element;
            this.next = next;
        }

        public E getElement() {

            return element;
        }

        public Node<E> getNext() {

            return next;
        }

        public void setElement(E element) {

            this.element = element;
        }

        public void setNext(Node<E> next) {

            this.next = next;
        }

        public String toString() {

            return ("[" + element + "] ");
        }
    }

    public Node<E> head;
    public Node<E> tail;
    public int total;      

    public SinglyLinkedList() {

        this.head = null;
        this.tail = null; 
        this.total = 0;
    }

    public E get(int index) {

        if (index < 0 || index > size()) {
            return null;
        }

        if (index == 0) {
            return head.getElement();
        }

        Node<E> singly = head.getNext();

        for (int i = 1; i < index; i ++) {

            if (singly.getNext() == null) {
              return null;
            }       

            singly = singly.getNext();      
        }

        System.out.println("\n" + singly.getElement());

        return singly.getElement(); 
    }

    public void add(E element) {
        Node<E> singlyAdd = new Node<E>(element);

        if (tail == null) {
            head = singlyAdd;
            tail = singlyAdd;
        } else {
            tail.setNext(singlyAdd);
            tail = singlyAdd;
        }     

        total++;
    }             

    public void display() {
        if (head == null) {
            System.out.println("empty list");
        } else {
            Node<E> current = head;
            while (current != null) {
                System.out.print(current.toString());
                current = current.getNext();
            }
        }

    }

    public boolean contains(E data) {

        if (head == null) {
            return false;
        }

        if (head.getElement() == data) {
            System.out.println(head);
            return true;                                
        }

        while (head.getNext() != null) {
            head = head.getNext();

            if (head.getElement() == data) {
                System.out.println(head);                
                return true;                               
            }             

        } 

        return false;         
    }       

    private Node<E> removeFirst() {
        if (head == null) {
            System.out.println("We cant delete an empty list");
        }    

        Node<E> singly = head;            
        head = head.getNext();
        singly.setNext(null);
        total--;

        return singly;     
    } 

    private Node<E> removeLast() {

        Node<E> nodeBefore;
        Node<E> nodeToRemove;     

        if (size() == 0) {
            System.out.println("Empty list");
        }    

        nodeBefore = head;

        for (int i = 0; i < size() - 2; i++) {
          nodeBefore = nodeBefore.getNext();
        }    

        nodeToRemove = tail;    

        nodeBefore.setNext(null);
        tail = nodeBefore;
        total--;

        return nodeToRemove;
    }       

    public E remove(int index) {      

        E hold = get(index);     

        if (index < 0 || index >= size()) {
            return null;
        } else if (index == 0) { 

            removeFirst();    
            return hold;
        } else {

            Node<E> current = head;
            for (int i = 1; i < index; i++) {                
                current = current.getNext();
            }  

            current.setNext(current.getNext().getNext());
            total--; 
            return hold;
        }       
    }       

    public int size() {
        return getTotal();
    }

    public boolean remove(E data) {      

        Node<E> nodeBefore, currentNode; 

        if (size() == 0) {
            System.out.println("Empty list");
        }            

        currentNode = head;

        if (currentNode.getElement() == data) {
            removeFirst();
        }

        currentNode = tail;
        if (currentNode.getElement() == data) {
            removeLast();
        }

        if (size() - 2 > 0) {
            nodeBefore = head;
            currentNode = head.getNext();
            for (int i = 0; i < size() - 2; i++) {
                if (currentNode.getElement() == data) {

                    nodeBefore.setNext(currentNode.getNext());
                    total--;
                    break;
                }

                nodeBefore = currentNode;
                currentNode = currentNode.getNext();
            } 
        } 

        return true;
    }

    public void clear() {

        while (head.getNext() != null) {    
            remove(head.getElement());    
        }

        remove(head.getElement());    
    }

    private int getTotal() {
        return total;
    } 
}

3 个答案:

答案 0 :(得分:2)

对于clear方法,我没有看到您对每个元素清理做了任何操作,返回类型为void,因此您只需要一个空列表。最简单的方法是简单地清除所有内容,例如在构造函数中:

public void clear() {
    this.head = null;
    this.tail = null; 
    this.total = 0;
}

另一条评论:

contains

while (head.getNext() != null) {
        head = head.getNext();

        if (head.getElement() == data) {
            System.out.println(head);                
            return true;                               
        }             
    } 

可能有两个问题(第一个适用于整个班级),

  1. 您与比较参考的== data进行比较,您可能希望将值与.equals(data)进行比较
  2. 编辑:即。 n.getElement().equals(data)代替n.getElement() == data

    (或者,如果ndata可能是null,则(data != null ? data.equals(n.getElement()) : data == n.getElement())

    1. 使用属性head作为修改列表状态的扫描变量。你真的想要吗?

答案 1 :(得分:2)

当您删除clear中的最后一个元素时出现问题:remove(head.getElement());。出于某种原因,您首先删除head,然后删除tail。但是在致电removeLast时,您使用head(已经是null)。在removeLast内,这就是该行,这会导致NullPointerExceptionnodeBefore.setNext(null);。 我的建议是编写@ {bali182建议的clear()方法:

public void clear() {
    this.head = null;
    this.tail = head;
    this.total = 0;
}

一个建议:如果您正在编写搜索或删除条目的方法,则在处理对象时不应使用==(甚至更好:在处理对象时根本不使用== )。您可能需要阅读this thread

答案 2 :(得分:0)

在clear方法中,您正在调用remove(head.getElement());,这意味着您正在尝试调用LinkedList的删除方法。并且由于您要覆盖每个功能,因此添加,您不会维护LinkedList的内部状态,因此您将获得异常。删除的代码是:

    public boolean remove(Object o) {
    if (o==null) {
        for (Entry<E> e = header.next; e != header; e = e.next) {
            if (e.element==null) {

因此,由于您没有使用LinkedList的功能,因此标头将为null并且执行header.next将返回NullPointerException。