简体   繁体   中英

Doubly Circularly Linked Lists in Java

I am trying to Implement a Doubly Circularly linked list, and am a little lost; I have my Doubly linked list, but am not exactly sure on how to make it circularly. I've read just have the last node point to the first node so would that be something like:

public void addLast(DNode v) {
addAfter(header, v);

}

Here is the code for my Doubly Linked list:

public class Dlist {

protected int size;
protected DNode header, trailer;

public Dlist() {
    size = 0;
    header = new DNode(null, null, null);
    trailer = new DNode(null, header, null);
    header.setNext(trailer);

}//end DList()

public int size() { return size; }

public boolean isEmpty() { return (size == 0); }


public DNode getFirst() throws IllegalStateException {
    if (isEmpty()) throw new IllegalStateException("List is empty");
    return header.getNext();
}//end isEmpty


public DNode getLast() throws IllegalStateException {
    if (isEmpty()) throw new IllegalStateException("List is empty");
    return trailer.getPrev();

}//end getLast


public DNode getPrev(DNode v) throws IllegalArgumentException {
    if (v == header) throw new IllegalArgumentException
        ("Cannot move back past the header of the list");
    return v.getPrev();
}


public DNode getNext(DNode v) throws IllegalArgumentException {
    if (v == trailer) throw new IllegalArgumentException
        ("Cannot move forward past the trailer of the list");
    return v.getNext();
}

public void addBefore(DNode v, DNode z) {
    DNode u = getPrev(v);
    z.setPrev(u);
    z.setNext(v);
    v.setPrev(z);
    u.setNext(z);
    size++;

}

public void addAfter(DNode v, DNode z) {
    DNode w = getNext(v);
    z.setPrev(v);
    z.setNext(w);
    w.setPrev(z);
    v.setNext(z);
    size++;
}

public void addFirst(DNode v) {
    addAfter(header, v);
}

public void addLast(DNode v) {
    addBefore(trailer, v);

}

public void remove(DNode v) {
    DNode u = getPrev(v);
    DNode w = getNext(v);

    w.setPrev(u);
    u.setNext(w);
    v.setPrev(null);
    v.setNext(null);
    size--;

}

public boolean hasPrev(DNode v) { return v != header;}

public boolean hasNext(DNode v) { return v != trailer; }

public String toString() {
    String s = "[";
    DNode v = header.getNext();
    while (v != trailer ) {
        s += v.getElement();
        v = v.getNext();
        if (v != trailer) {
            s += ",";

        }
        s+= "]";
        return s;
    }
    return s;
}

EDIT: DNode;

public class DNode {
protected String element;
protected DNode next, prev;

public DNode(String e, DNode p, DNode n) {
    element = e;
    prev = p;
    next = n;

}

public String getElement() {return element;}

public DNode getPrev() { return prev; }

public DNode getNext() { return next; }

public void setElement(String newElem) { element = newElem; }

public void setPrev(DNode newPrev) { prev = newPrev; }

public void setNext(DNode newNext) {next = newNext;}
}

You now have a header and trailer pseudo-node:

header <--> first <--> second <--> ... <--> last <--> trailer

Instead, you would have to connect the first and last in both directions.

        .-> first  <--> second <--> ... <--> last <-.
        |                                           |
        '-------------------------------------------'

Alternatively, you could also merge header and trailer in one node, but this then is no "pure" circularly linked list, since you have to step over the header/trailer node on traversal.

        .-> first  <--> second <--> ... <--> last <--> header/trailer <-.
        |                                                               |
        '---------------------------------------------------------------'

A circular list has no header, trailer, first nor last element. This forces special cases on you.

You can either have a pseudo element or not.

If you have a pseudo element, then you need to handle it as a special case in getNext and getPrevious as it must be skipped over, but you don't need to worry about what happens when the list is empty or if you are removing something important.

If you have no pseudo element, then there are no special cases for next and previous, but there is a special case for add when the list is empty and remove if you remove the node you are using to link into the list with.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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