目录
特点:
比起单链表,节点多了一个指向前一个节点的指针,弥补了单链表节点不能找到前面一个节点的缺陷,并且需要链表倒序时,可以从尾部开始遍历,查找元素时,可以从较近的一方开始遍历,因为节点多了一个属性,所有所用空间会比单链表大。
结构图:
节点类:
class Node{
public Integer data;
public Node next;
public Node pre;
public Node() {}
public Node(Integer data) {
this.data = data;
}
}
双链表类
public class DoubleLinkedList {
public Node head;//头指针,指向头节点
public Node rear;//尾节点,链表最后一个节点
private Integer size;//节点个数
public DoubleLinkedList() {
this.head = new Node();
this.size = 0;
}
public Integer getSize() {
return size;
}
}
添加节点
把节点添加到链表尾部
- 判断头指针是否指向null,如果是,则让头指针指向新节点 ,并且让尾节点等于它
- 如果不是,则让尾节点指向它
public void add(Integer data) {
Node p = new Node(data);
if(head.next == null) {
head.next = p;//让头指针指向新节点
p.pre = head;
rear = p;//让尾节点等于它
}else {
rear.next = p;//让尾节点指向它
p.pre = rear;
rear = p;
}
size++;
}
查找指定位置元素
判断是否超出元素个数,再判断是从头指针遍历近,还是尾节点开始遍历近,然后找到节点返回
public Node findIndex(int index) {
Node temp = null;
if(index >= size) {
System.out.println("超过元素个数!");
return null;
}else if(index*2 < size){ //从头指针开始遍历
temp = head;
int count = 0;
while(count<=index) {
count++;
temp = temp.next;
}
}else {//从尾节点开始遍历
temp = rear;
int count = size - 1;
while(count>index) {
count--;
temp = temp.pre;
}
}
return temp;
}
删除
删除第一次出现的data
temp.pre.next = temp.next; 让它的前一个节点next等于它的后一个节点
temp.next.pre = temp.pre; 让它的后一个节点pre等于它的前一个节点
public void removeByData(Integer data) {
Node temp = head;
while(temp.next != null) {
temp = temp.next;
if(temp.data == data) {
if(temp.next == null) {//说明是最后一个节点
rear = temp.pre;//尾节点指向现在的倒数第二个节点
}
temp.pre.next = temp.next;
temp.next.pre = temp.pre;
size--;
}
}
}
删除指定位置的元素
判断是否超出元素个数,再判断是从头指针遍历近,还是尾节点开始遍历近,然后找到节点删除
public void removeByIndex(Integer index) {
Node temp = findIndex(index);//查找到该节点
if(temp.next == null) {//说明是最后一个节点
rear = temp.pre;//尾节点指向现在的倒数第二个节点
}
temp.pre.next = temp.next;
temp.next.pre = temp.pre;
size--;
}
插入数据
找到该位置的节点,然后插入让它前一个节点指向要插入的节点,新插入的节点指向原本该位置的节点
public void insert(int index,int data) {
Node temp = findIndex(index);//查找到该节点
if(temp != null) {
Node p = new Node(data);//创建要插入的节点
temp.pre.next = p;//插入位置的前一个节点指向新节点
p.pre = temp.pre;
p.next = temp; //新节点指向原来位置的节点
temp.pre = p;
size++;
}
}
遍历链表所有元素
public void showAll() {
Node temp = head;
while(temp.next !=null) {
temp = temp.next;
System.out.print(temp.data + " ");
}
}