How to do a cyclic doubly link list add method in java

故事扮演 提交于 2019-12-13 03:52:36

问题


I am implementing the add(E) method in the cyclic DoublyLinkedList class as well as the Node inner class.

Node should be implemented as a private inner class.

DoublyLinkedList's "first" attribute should point to the first node in the list. Its "size" attribute should store the number of elements in the list.

I am struggling on my add method, because it feels like nothing is wrong and I don't know what else I can add this this code that can fix it.

Therefore a brief introduction on what the add method should do.

The add(E) method should add the value parameter to the end of the list. Be sure to address the case in which the list is empty and/or the added element is the first in the list.

Here's my code:

public class DoublyLinkedList<E>
{
private Node first;
private int size;

@SuppressWarnings("unchecked")
public void add(E value)
{
    if(first == null)
    {
        first = new Node(value, null, null);
        first.next = first;
        first.prev = first;
    }
    else
    {
        first = new Node(value, first.next, first.prev);
        first.next = first.prev;
        first = first.next;
        first.prev = first;
    }
    size++;
}
private class Node<E>
{
    private E data;
    private Node next;
    private Node prev;

    public Node(E data, Node next, Node prev)
    {
        this.data = data;
        this.next = next;
        this.prev = prev;
    }
  }
 }

回答1:


Code fixed with minimal change (just the else case in add):

class DoublyLinkedList<E>
{
    private Node first;
    private int size;

    public void add(E value)
    {
        if(first == null)
        {
            first = new Node(value, null, null);
            first.next = first;
            first.prev = first;
        }
        else
        {
            first.prev.next = new Node(value, first, first.prev);
            first.prev = first.prev.next;
        }
        size++;
    }

    private class Node<E>
    {
        private E data;
        private Node next;
        private Node prev;

        public Node(E data, Node next, Node prev)
        {
            this.data = data;
            this.next = next;
            this.prev = prev;
        }
    }
}



回答2:


EDIT:

One mistake is here: Instead of this line this.next = prev; it should have this.prev = prev;

However, if you fix this line the code will still not work. This is a simplified version of your code that works.

public class DoublyLinkedList<E> {

    private static class Node<E> {

        private final E data;
        private Node<E> next;
        private Node<E> prev;

        Node(E data) {
            this.data = data;
            this.next = this;
            this.prev = this;
        }

        Node(E data, Node<E> next) {
            this.data = data;
            this.next = next;
            next.prev = this;
        }
    }

    private Node<E> head;
    private Node<E> tail;
    private int size;

    public void add(E value) {
        if (this.head == null) {
            this.head = new Node<>(value);
            this.tail = head;
        } else {
            this.head = new Node<>(value, head);
            this.head.prev = this.tail;
            this.tail.next = head;
        }
        size++;
    }

    public void forEach(Consumer<E> consumer) {
        Node<E> node = this.head;

        if (node != null) {
            do {
                consumer.accept(node.data);
                node = node.next;
            } while (node != this.head);
        }
    }

    public static void main(String[] args) {
        DoublyLinkedList<Integer> list = new DoublyLinkedList<>();

        list.add(1);
        list.add(2);
        list.add(3);

        list.forEach(e -> System.out.print(e + ", "));
    }

}

What I've done: in order to create a circular double linked list I keep a reference to the tail.




回答3:


Here is a sample implementation for your case -

import java.util.Iterator;

public class DoublyLinkedList<E> {

    // A reference to the root node
    private Node<E> root = null;

    // attribute for storing the size of the linked list
    private int countOfNodes = 0;

    // attribute that indicates if the linked list would be iterated in a cycle
    private boolean isCircular = false;

    /**
     * The linked list Node class
     * 
     * @param <E>
     */

    @SuppressWarnings("hiding")
    class Node<E> {
        // attribute for storing the value
        private E data;

        // attributes for storing the linked list references
        private Node<E> previousNode = null;
        private Node<E> nextNode = null;

        public Node() {
            super();
        }

        public Node(E data) {
            super();
            this.data = data;
        }

        public Node<E> getPreviousNode() {
            return previousNode;
        }

        public void setPreviousNode(Node<E> previousNode) {
            this.previousNode = previousNode;
        }

        public Node<E> getNextNode() {
            return nextNode;
        }

        public void setNextNode(Node<E> nextNode) {
            this.nextNode = nextNode;
        }

        public E getData() {
            return data;
        }

        public void setData(E data) {
            this.data = data;
        }
    }

    /**
     * The iterator implementation
     */
    @SuppressWarnings("hiding")
    class DoublyLinkedListIterator<E> implements Iterator<E> {
        private Node<E> currentNode = null;

        public DoublyLinkedListIterator(Node<E> startNode) {
            super();
            this.currentNode = startNode;
        }

        @Override
        public boolean hasNext() {
            return (this.currentNode != null);
        }

        @SuppressWarnings("unchecked")
        @Override
        public E next() {
            E data = currentNode.getData();
            currentNode = currentNode.getNextNode();

            if (currentNode == null && DoublyLinkedList.this.isCircular()) {
                this.currentNode = (Node<E>) DoublyLinkedList.this.getRoot();
            }

            return data;
        }
    }

    public DoublyLinkedList() {
        super();
    }

    public boolean isCircular() {
        return this.isCircular;
    }

    public void setCircular(boolean isCircular) {
        this.isCircular = isCircular;
    }

    public Node<E> getRoot() {
        return root;
    }

    public void setRoot(Node<E> root) {
        this.root = root;
    }

    public int size() {
        return this.countOfNodes;
    }

    public Iterator<E> iterator() {
        return new DoublyLinkedListIterator<>(this.getRoot());
    }

    public void add(E value) {
        Node<E> node = new Node<E>(value);
        addAfter(getLastNode(), node);
        this.countOfNodes++;
    }

    public Node<E> getLastNode() {  
        Node<E> lastNode = null;

        Node<E> node = getRoot();
        while (node != null) {
            lastNode = node;
            node = node.getNextNode();
        }

        return lastNode;
    }

    public void addAfter(Node<E> parentNode, E value) {
        Node<E> newNode = new Node<E>(value);
        addAfter(parentNode, newNode);
    }

    public void addAfter(Node<E> parentNode, Node<E> newNode) {
        if (parentNode == null) {
            this.setRoot(newNode);
        } else {
            parentNode.setNextNode(newNode);
        }
    }

    public void addBefore(Node<E> parentNode, E value) {
        Node<E> newNode = new Node<E>(value);
        addBefore(parentNode, newNode);
    }

    public void addBefore(Node<E> parentNode, Node<E> newNode) {
        if (parentNode == null) {
            this.setRoot(newNode);
        } else {
            Node<E> prevNode = parentNode.getPreviousNode();
            parentNode.setPreviousNode(newNode);
            newNode.setNextNode(parentNode);            
            newNode.setPreviousNode(prevNode);

            if (newNode.getPreviousNode() == null) {
                this.setRoot(newNode);
            }
        }
    }
}

And, following is a test -

import static org.junit.jupiter.api.Assertions.fail;

import java.util.Iterator;

import org.junit.jupiter.api.Test;

class DoublyLinkedListTest {
    private final int initialSize = 4;

    private DoublyLinkedList<String> list = new DoublyLinkedList<String>() {{
        setCircular(true);

        for(int i = 0; i < initialSize; i++) {
            add("Data " + (i + 1));
        }
    }};

    public DoublyLinkedListTest() {
        super();
    }

    @Test
    void testListSize() {
        if (list.size() != initialSize) {
            fail(String.format("Expected value for the list's size is %d, whereas obtained value is %d", 4, list.size()));
        }
    }

    @Test
    void testLastElement() {
        String lastAddedValue = list.getLastNode().getData();
        String expectedValue = "Data 4";

        if (!expectedValue.equals(lastAddedValue)) {
            fail(String.format("Expected value for the last node is %s, whereas obtained value is %s", expectedValue, lastAddedValue));
        }
    }

    @Test
    void testAddElementOnTop() {
        list.addBefore(list.getRoot(), "Data 5");

        String lastAddedValue = list.getRoot().getData();
        String expectedValue = "Data 5";

        if (!expectedValue.equals(lastAddedValue)) {
            fail(String.format("Expected value for the last node is %s, whereas obtained value is %s", expectedValue, lastAddedValue));
        }
    }

    @Test
    void testCircularIteration() {
        Iterator<String> iterator = list.iterator();

        int counter = 0;
        final int expectedValue = (initialSize + 1) * 2;

        while(iterator.hasNext()) {
            counter++;

            if (counter == expectedValue) {
                break;
            }
        }

        if (counter != expectedValue) {
            fail(String.format("Expected value for the iteration count is %d, whereas obtained value is %d", expectedValue, counter));
        }
    }
}


来源:https://stackoverflow.com/questions/55190980/how-to-do-a-cyclic-doubly-link-list-add-method-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!