双向链表:
就是有双向指针 即 双向的链域
链结点的结构:
┌────┬────┬────────┐
│data│next│previous│
└────┴────┴────────┘
双向链表不必是双端链表(持有对最后一个链结点的引用),双端链表插入时是双向的
有两条链:一条从头到尾,一条从尾到头,删除遍历时也是双向的
/**
* 双向链表
*
* @author stone
*/
public class DoublyLinkedList<T> {
private Link<T> head; //首结点
private Link<T> rear; //尾部指针
public DoublyLinkedList() {
}
public T peekHead() {
if (head != null) {
return head.data;
}
return null;
}
public T peekRear() {
if (rear != null) {
return rear.data;
}
return null;
}
public boolean isEmpty() {
return head == null;
}
public void insertFirst(T data) {// 插入 到 链头
Link<T> newLink = new Link<T>(data);
if (isEmpty()) {//为空时,第1次插入的新结点为尾结点
rear = newLink;
} else {
head.previous = newLink; //旧头结点的上结点等于新结点
}
newLink.next = head; //新结点的下结点旧头结点
head = newLink; //赋值后,头结点的下结点是旧头结点,上结点null
}
public void insertLast(T data) {//在链尾 插入
Link<T> newLink = new Link<T>(data);
if (isEmpty()) {
head = newLink;
} else {
rear.next = newLink;
}
newLink.previous = rear;
rear = newLink; //赋值后,尾结点的上结点是旧尾结点,下结点null
}
public T deleteHead() {//删除 链头
if (isEmpty()) return null;
Link<T> temp = head;
head = head.next; //变更首结点,为下一结点
if (head != null) {
head.previous = null;
} else {
rear = null;
}
return temp.data;
}
public T deleteRear() {//删除 链尾
if (isEmpty()) return null;
Link<T> temp = rear;
rear = rear.previous; //变更尾结点,为上一结点
if (rear != null) {
rear.next = null;
} else {
head = null;
}
return temp.data;
}
public T find(T t) {//从头到尾find
if (isEmpty()) {
return null;
}
Link<T> find = head;
while (find != null) {
if (!find.data.equals(t)) {
find = find.next;
} else {
break;
}
}
if (find == null) {
return null;
}
return find.data;
}
public T delete(T t) {
if (isEmpty()) {
return null;
}
Link<T> current = head;
while (!current.data.equals(t)) {
current = current.next;
if (current == null) {
return null;
}
}
if (current == head) {
head = head.next;
if (head != null) {
head.previous = null;
}
} else if (current == rear) {
rear = rear.previous;
if (rear != null) {
rear.next = null;
}
} else {
//中间的非两端的结点,要移除current
current.next.previous = current.previous;
current.previous.next = current.next;
}
return current.data;
}
public boolean insertAfter(T key, T data) {//插入在key之后, key不存在return false
if (isEmpty()) {
return false;
}
Link<T> current = head;
while (!current.data.equals(key)) {
current = current.next;
if (current == null) {
return false;
}
}
Link<T> newLink = new Link<T>(data);
/* if (current == head) {//若为头,考虑头的后指针,原头后指针的前指针,新链结点的前后指针
newLink.next = current.next;
current.next.previous = newLink;
// newLink.previous = current;
// current.next = newLink;
} else if (current == rear) {
// newLink.next = null;
rear = newLink;
// current.next = newLink;
// newLink.previous = current;
} else {
newLink.next = current.next;
current.next.previous = newLink;
// current.next = newLink;
// newLink.previous = current;
}*/
//上面的判断简写成:
if (current == rear) {
rear = newLink;
} else {
newLink.next = current.next;
current.next.previous = newLink;
}
current.next = newLink;
newLink.previous = current;
return true;
}
public void displayList4Head() {//从头开始遍历
System.out.println("List (first-->last):");
Link<T> current = head;
while (current != null) {
current.displayLink();
current = current.next;
}
}
public void displayList4Rear() {//从尾开始遍历
System.out.println("List (last-->first):");
Link<T> current = rear;
while (current != null) {
current.displayLink();
current = current.previous;
}
}
public int size() {//从头开始遍历
int count = 0;
System.out.println("List (first-->last):");
Link<T> current = head;
while (current != null) {
count++;
current = current.next;
}
return count;
}
class Link<T> {//链结点
T data; //数据域
Link<T> next; //后继指针,结点 链域
Link<T> previous; //前驱指针,结点 链域
Link(T data) {
this.data = data;
}
void displayLink() {
System.out.println("the data is " + data.toString());
}
}
public static void main(String[] args) {
DoublyLinkedList<Integer> list = new DoublyLinkedList<Integer>();
list.insertLast(1);
list.insertFirst(2);
list.insertLast(3);
list.insertFirst(4);
list.insertLast(5);
list.displayList4Head();
Integer deleteHead = list.deleteHead();
System.out.println("deleteHead:" + deleteHead);
list.displayList4Head();
Integer deleteRear = list.deleteRear();
System.out.println("deleteRear:" + deleteRear);
list.displayList4Rear();
System.out.println("find:" + list.find(6));
System.out.println("find:" + list.find(3));
System.out.println("delete find:" + list.delete(6));
System.out.println("delete find:" + list.delete(1));
list.displayList4Head();
System.out.println("----在指定key后插入----");
list.insertAfter(2, 8);
list.insertAfter(2, 9);
list.insertAfter(9, 10);
list.displayList4Head();
}
}
打印
List (first-->last):
the data is 4
the data is 2
the data is 1
the data is 3
the data is 5
deleteHead:4
List (first-->last):
the data is 2
the data is 1
the data is 3
the data is 5
deleteRear:5
List (last-->first):
the data is 3
the data is 1
the data is 2
find:null
find:3
delete find:null
delete find:1
List (first-->last):
the data is 2
the data is 3
----在指定key后插入----
List (first-->last):
the data is 2
the data is 9
the data is 10
the data is 8
the data is 3
/**
* 双端队列 两端插入、删除
* 基于双向链表实现
* @author stone
*/
public class QueueBaseOfDoublyList<T> {
private DoublyLinkedList<T> list;
public QueueBaseOfDoublyList() {
list = new DoublyLinkedList<T>();
}
// 插入队头
public void insertLeft(T t) {
list.insertFirst(t);
}
// 插入队尾
public void insertRight(T t) {
list.insertLast(t);
}
// 移除队头
public T removeLeft() {
return list.deleteHead();
}
// 移除队尾
public T removeRight() {
return list.deleteRear();
}
// 查看队头
public T peekLeft() {
return list.peekHead();
}
// 查看队尾
public T peekRight() {
return list.peekRear();
}
public void displayQueue() {
list.displayList4Head();//从头开始遍历
}
public boolean isEmpty() {
return list.isEmpty();
}
public int size() {
return list.size();
}
public static void main(String[] args) {
QueueBaseOfDoublyList<Integer> list = new QueueBaseOfDoublyList<Integer>();
list.insertLeft(1);
list.insertRight(2);
list.insertLeft(3);
list.insertRight(4);
list.displayQueue();
System.out.println("size:" + list.size());
list.removeLeft();
System.out.println("size:" + list.size());
list.displayQueue();
list.removeRight();
System.out.println("size:" + list.size());
list.displayQueue();
}
}
打印
List (first-->last):
the data is 3
the data is 1
the data is 2
the data is 4
List (first-->last):
size:4
List (first-->last):
size:3
List (first-->last):
the data is 1
the data is 2
the data is 4
List (first-->last):
size:2
List (first-->last):
the data is 1
the data is 2