Search code examples
javagenericsgeneric-listcircular-list

CircularLinkedList remove method not working


I am experiencing a problem with my circularlinkedlist. it is a list, that is currently populated with Nodes, which each contains an object of my Person class.

The thing that im trying to do is:

Remove the node, 5 steps ahead of the start Node. It works fine, until i reach a point where my list only contains 1 Node. Then it gives me this error, when calling randomStart() and trying to print the list.

Exception in thread "main" java.lang.NullPointerException at cirkulærliste.CircularLinkedList.randomStart(CircularLinkedList.java:60) at cirkulærliste.Test.main(Test.java:98)

if anyone could take a look at my CircularLinkedList class and my Test class, it would be nice. :)

public class CircularLinkedList<E extends Comparable<? super E>> {

    private Node<E> cursor;
    private Node<E> start;
    private int size = 0;

    public CircularLinkedList() {
        setCursor(null);
    }

    /**
     * tilføjer personer
     * @param p
     */
    public void addElement(E e) {
        Node<E> newNode = new Node<E>(e, null);
        Node<E> tempNext = cursor;

        if(cursor == null){
            cursor = newNode;
            cursor.setNext(cursor);
            cursor.setPrev(cursor);
        } else if(size > 1){
            newNode.setPrev(cursor);
            newNode.setNext(cursor.getNext());
            cursor.getNext().setPrev(newNode);
            cursor.setNext(newNode);

        } else {
            newNode.setPrev(cursor);
            newNode.setNext(cursor);
            cursor.setPrev(newNode);
            cursor.setNext(newNode);
        }
        size++;
    }

    /**
     * udskriver personerne i den rækkefølge de står i listen
     */
    public void print() {
        Node<E> tempNode = start;
        while (!tempNode.getNext().equals(start)) {
            System.out.println(tempNode);
            tempNode = tempNode.getNext();
        }
        System.out.println(tempNode);
    }

    /**
     * en tilfældig person i den cirkulæreliste vælges som start i listen
     */
    public void randomStart() {
        int size = 1;
        Node<E> tempNode = cursor.getNext();
        // NPE occurs here
        while (!tempNode.getNext().equals(cursor.getNext())) {
            tempNode = tempNode.getNext();
            size++;
        }
        Random randomizer = new Random();
        int chosen = randomizer.nextInt(size);
        for (int i = 0; i <= chosen; i++) {
            tempNode = tempNode.getNext();
        }
        start = tempNode;
    }

    /**
     * fjerner den person fra listen der ligger 5 pladser fra start i listen. Personen der fjernes returneres.
     */
    public Node<E> remove() {
        Node<E> tmpNode = start;

        for(int i = 1; i < 5; i++){
            tmpNode = tmpNode.getNext();
        }

        Node<E> tmpNode2 = tmpNode.getNext();


        if(tmpNode.getNext().equals(start)){
            Node<E> tmp3 = start.getNext();
            tmpNode.setNext(start.getNext());
            start.getNext().setPrev(tmpNode);
            start = tmp3;

        } else {

        tmpNode.setNext(tmpNode.getNext().getNext());
        tmpNode.getNext().setPrev(tmpNode);
        tmpNode2.setNext(null);
        tmpNode2.setPrev(null);
        }

        return tmpNode2;

    }


    public void setCursor(Node<E> cursor) {
        this.cursor = cursor;
    }


    public Node<E> getCursor() {
        return cursor;
    }


    public void setStart(Node<E> start) {
        this.start = start;
    }


    public Node<E> getStart() {
        return start;
    }
}



package cirkulærliste;

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        CircularLinkedList<Person> list = new CircularLinkedList<Person>();


        list.addElement(new Person("Thomas", 1));
        list.addElement(new Person("Bjarne", 2));
        list.addElement(new Person("Camilla", 3));
        list.addElement(new Person("Bo", 4));
        list.addElement(new Person("Bobo", 5));
        list.addElement(new Person("Martin", 6));
        list.addElement(new Person("Søren", 7));
        list.addElement(new Person("Luller", 8));

        list.randomStart();

        System.out.println("START: " + list.getStart());
        System.out.println("-----------------------------------------");
        list.print();
        System.out.println("-----------------------------------------");

        System.out.println("Deleting: " + list.remove());
        System.out.println("-----------------------------------------");

        list.randomStart();
        System.out.println("START: " + list.getStart());
        System.out.println("-----------------------------------------");
        list.print();

        System.out.println("-----------------------------------------");

        System.out.println("Deleting: " + list.remove());
        System.out.println("-----------------------------------------");

        list.randomStart();
        System.out.println("-----------------------------------------");
        System.out.println("START: " + list.getStart());
        System.out.println("-----------------------------------------");
        list.print();

        System.out.println("-----------------------------------------");

        System.out.println("Deleting: " + list.remove());
        System.out.println("-----------------------------------------");

        list.randomStart();
        System.out.println("-----------------------------------------");
        System.out.println("START: " + list.getStart());
        System.out.println("-----------------------------------------");
        list.print();

        System.out.println("-----------------------------------------");

        System.out.println("Deleting: " + list.remove());
        System.out.println("-----------------------------------------");

        list.randomStart();
        System.out.println("-----------------------------------------");
        System.out.println("START: " + list.getStart());
        System.out.println("-----------------------------------------");
        list.print();

        System.out.println("-----------------------------------------");

        System.out.println("Deleting: " + list.remove());
        System.out.println("-----------------------------------------");

        list.randomStart();
        System.out.println("-----------------------------------------");
        System.out.println("START: " + list.getStart());
        System.out.println("-----------------------------------------");
        list.print();


        System.out.println("-----------------------------------------");

        System.out.println("Deleting: " + list.remove());
        System.out.println("-----------------------------------------");

        list.randomStart();
        System.out.println("-----------------------------------------");
        System.out.println("START: " + list.getStart());
        System.out.println("-----------------------------------------");
        list.print();


        System.out.println("-----------------------------------------");

        System.out.println("Deleting: " + list.remove());
        System.out.println("-----------------------------------------");

        list.randomStart();
        System.out.println("-----------------------------------------");
        System.out.println("START: " + list.getStart());
        System.out.println("-----------------------------------------");
        list.print();


    }

}

Solution

  • Unless I'm mistaken there's no reason to do this:

    int size = 1;
    Node<E> tempNode = cursor.getNext();
    // NPE occurs here
    while (!tempNode.getNext().equals(cursor.getNext())) {
        tempNode = tempNode.getNext();
        size++;
    }
    

    in randomStart().

    You already increment a "size" int everytime the addElement() method is called. Just use this.size or just size after removing the above code.

    Edit: I think your remove() method was more complex than it needed to be.

    Edit: This now allows you to remove the final Node by making a special case of the size being equal to 1. It also returns the Node which has just been deleted.

    public Node<E> remove() {
        Node<E> tmpNode = start;
        if (size > 1) {
            // Move five nodes from the start
            for(int i = 0; i < 5; i++)
                tmpNode = tmpNode.getNext();
    
            // Move the start and cursor nodes if
            // they are about to be removed.
            if (tmpNode.equals(start))
                start = start.getNext();
            if (tmpNode.equals(cursor))
                cursor = cursor.getNext();
    
            // Remove the fifth node
            Node<E> next = tmpNode.getNext();
            Node<E> prev = tmpNode.getPrev();
            prev.setNext(next);
            next.setPrev(prev);
    
            size--;
        } else if (size == 1) {
            start = null;
            cursor = null;
    
            size--;
        }
        return tmpNode;
    }
    

    Let me know if this helps!