基本概念
循环链表:将单链表中最后一个结点的next指向头结点或者空指针,就使得整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表。
双向链表:是在单链表的每个结点中,再设置一个指向其前驱结点的指针域prior,在双向链表的结点中有两个指针域,一个next指向直接后继,一个prior指向直接前驱。
双向循环链表:将二者结合起来,结点有两个指针域,且最后一个结点的next指向头结点。头结点的上一个结点指向最后一个结点。
双向循环链表遍历时的判断结束的条件是当前结点的下一个结点是否是头结点,如果是表示当前结点是最后一个结点。
如果链表中只有一个结点,它的直接前驱和直接后继就是它自己。
插入时实现的原理:
- 将新结点的上一个结点指最后一个结点,即head的上一个结点
- 将新结点的下一个结点指向head结点
- 将最后一个结点的下一个结点指向新结点
- 将head的上一个结点指向新结点
注意,如果是头插法,每次四步完成之后 要将头指针指向新结点
删除时的原理:
- 将temp.next赋值给temp.prior.next
- 将temp.prior赋值给temp.next.prior
实现代码
结点代码
public class Node<T extends Comparable<T>> {
T value;
Node next; //指向直接后继
Node prior; //指向直接前驱
public Node(){
this(null);
}
public Node(T value){
this.value = value;
next = null;
}
}
双向循环链表代码
public class DoubleCircularLinkedList<T extends Comparable<T> >{
private Node head;
publicDoubleCircularLinkedList(){
head = null;
}
private boolean isEmpty() {
return head == null;
}
//插入,不带头结点的双向循环列表头插法和尾插法的位置是一样的
// 区别是头插法每次插入完成后需要将头指针指向刚插入的结点
public void addHead(T value){
Node n = new Node(value);
if (isEmpty()){ //如果是空的。
head = n;
head.next = head;
head.prior = head;
}else {
n.prior = head.prior; //n的值赋值给head;
n.next = head; //n的下一个结点是头指针的下一个结点
head.prior.next = n; //n赋值给head的上一个结点的下一个结点
head.prior = n; //将n赋值给head下一个结点的前驱
head = n; //每次将头指针指向刚插入的元素
}
}
public void add(T value){
addLast(value);
}
public void addLast(T value) {
Node n = new Node(value);
if (isEmpty()){ //如果是空的。
head = n;
head.next = head;
head.prior = head;
}else {
Node temp = head;
while (temp.next != head){ //循环完之后temp就是尾结点
temp = temp.next;
}
n.prior = head.prior; //n的值赋值给head;
n.next = head; //n的下一个结点是头指针的下一个结点
head.prior.next = n; //n赋值给head的上一个结点的下一个结点
head.prior = n; //将n赋值给head下一个结点的前驱
}
}
//删除值为value的所有结点
public void remove(T value){
Node temp = head;
while (temp.prior.next == head) {
if (temp.value.equals(value)) { //第一个结点
temp.prior.next = temp.next;
temp.next.prior = temp.prior;
head = head.next;
}
temp = temp.next;
}
while (temp.next != head){ //中间的结点
if (temp.value.equals(value)){
temp.prior.next = temp.next;
temp.next.prior = temp.prior;
}
temp = temp.next;
}
if (temp.value.equals(value)){ //最后一个结点
temp.prior.next = temp.next;
temp.next.prior = temp.prior;
}
}
//修改第i个结点的value值
public T set(int i,T value){
Node temp = head;
while (temp.next != head && i-- != 0){
temp = temp.next;
}
T data = (T)temp.value;
temp.value = value;
return data;
}
//查找该value是第一次出现是第几个结点
public int search(T value){
int num = 0;
Node temp = head;
while (temp.next != head){
if (temp.value.equals(value)){
return num;
}
temp = temp.next;
num++;
}
if (temp.value.equals(value)){
return num;
}else{
return -1;
}
}
//打印
public void show(){
Node temp = head;
while (temp.next != head){
System.out.println(temp.value);
temp = temp.next;
}
System.out.println(temp.value);
}
}
测试代码
public class Test {
public static void main(String[] args) {
DoubleCircularLinkedList<String> doubleCircularLinkedList = new DoubleCircularLinkedList<>();
doubleCircularLinkedList.add("aa");
doubleCircularLinkedList.add("aa");
doubleCircularLinkedList.add("bb");
doubleCircularLinkedList.add("cc");
doubleCircularLinkedList.set(1,"dd");
System.out.println(doubleCircularLinkedList.search("aa"));
// doubleCircularLinkedList.remove("aa");
// doubleCircularLinkedList.addHead("cc");
// doubleCircularLinkedList.addHead("bb");
// doubleCircularLinkedList.addHead("aa");
doubleCircularLinkedList.show();
}
}