双向循环链表:每个结点包含了数据、直接前驱地址指针和直接后驱地址指针,头结点的直接前驱指向尾结点,尾结点的直接后驱指向头结点,头尾相连构成一个可正可反的圆环。可以形象的理解成一群孩子手拉手牵成一个圆圈,从头一个孩子开始可以从左往右报数,也可以从右往左开始报数。
优点:双向循环链表可以迅速的获取当前数据的前驱数据,解决了单向循环链表从头开始遍历的麻烦
结点类:
/**
* 结点: 左指针+数据+右指针
*/
public class DoubleNode<T> {
private DoubleNode<T> left,right;
private T data;
DoubleNode(T data) {
this(data,null,null);
}
DoubleNode() {
this(null,null,null);
}
DoubleNode(T data,DoubleNode<T> left,DoubleNode<T> right) {
this.data = data;
this.left = left;
this.right = right;
}
public T getData() {
return this.data;
}
public DoubleNode<T> getLeft() {
return this.left;
}
public DoubleNode<T> getRight() {
return this.right;
}
public void setData(T data) {
this.data = data;
}
public void setRight(DoubleNode<T> right) {
this.right = right;
}
public void setLeft(DoubleNode<T> left) {
this.left = left;
}
public String toString() {
return getData().toString();
}
}
实现类
public class DoubleLinkList<T> {
public DoubleNode<T> head;
//建空表,带头结点
DoubleLinkList() {
this(null);
}
//具有头结点
public DoubleLinkList(T element) {
// TODO Auto-generated constructor stub
if(element==null){
head=new DoubleNode<T>(element,null,null);
head.setRight(head);
head.setLeft(head);
}else {
//单个数据结点的状况
DoubleNode<T> headRight = new DoubleNode<T>(element,null,null);
head = new DoubleNode<T>(null,headRight,headRight);
headRight.setLeft(head);
headRight.setRight(head);
}
}
//表长
/*
* 思路:
* 1. 用temp记住对象
* 2. 遍历,假如temp不等于最后一个元素,还会遍历下去
* 3. 循环增加长度
*/
public int Length() {
int len = 0;
DoubleNode<T> temp = head;
while(temp.getRight() != head) {
len++;
temp = temp.getRight();
}
return len;
}
//取下标index处的数据
/**
* 思路:
* 1. 假如在0的方位,则是获取第一个,利用hean.getRight
* 2. 假如是len,则是获取最后一个,利用head.getleft
* 3. 假如在中间就通过遍历,获取元素
* @param index
* @return
*/
public T getElement(int index) {
if(index <= 0) {
return head.getRight().getData();
}
int len = Length();
if(index >= len) {
return head.getLeft().getData();
}
T element = null;
if(index > 0 && index < len) {
int k = 0;
DoubleNode<T> temp = head;
//此处只能用while不能用if,用错好几次
while(k <= index && temp.getRight() != head) {
k++;
temp = temp.getRight();
}
element = temp.getData();
}
return element;
}
//尾添
/**
* 思路:
* 1. 定义最后一个的Node,左边为head.getLeft(最后一个),右边为head
* 2. 然后设置左右一个的右边为node,head的左边为Node
*
* @param element
* @return
*/
public boolean add(T element) {
if(element == null) return false;
DoubleNode<T> node = new DoubleNode<T>(element,head.getLeft(),head);
head.getLeft().setRight(node);
head.setLeft(node);
return true;
}
//首添
public boolean addHead(T element) {
if(element == null) return false;
DoubleNode<T> node = new DoubleNode<T>(element,head,head.getRight());
head.getRight().setLeft(node);
head.setRight(node);
return false;
}
//表index处,添加新数据element
public boolean addByIndex(int index, T element) {
if(index <= 0) {
return addHead(element);
}else if(index >= Length()) {
return add(element);
}else {
int k = 0;
DoubleNode<T> temp = head;
//此处只能用while不能用if,用错好几次
while(k <= index && temp.getRight() != head) {
k++;
temp = temp.getRight();
}
DoubleNode<T> node = new DoubleNode<T>(element,temp.getLeft(),temp);
temp.getLeft().setRight(node);
temp.setLeft(node);
}
return true;
}
}