简体   繁体   English

Java中的双向循环链接列表

[英]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; 编辑: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: 现在,您有一个headertrailer伪节点:

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. 如果您有伪元素,则需要在getNextgetPrevious中将其作为特殊情况处理,因为必须跳过它,但是您不必担心列表为空或要删除某些内容时会发生什么重要。

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. 如果没有伪元素,则下一个和上一个没有特殊情况,但是当列表为空时,则有添加的特殊情况;如果删除了用于链接到列表的节点,则有特殊的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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