学习目标:
- 掌握双向链表
- 掌握双向循环链表
学习内容:
- 双向链表
- 双向循环链表
为了方便操作,双向链表和双向循环链表都是带哨兵实现。
双向链表:
双向链表:在单链表的每个结点中,再设置一个指向其前驱结点的指针域。
1 定义双向链表
private static class Node {
private Node prev;
private int value;
private Node next;
public Node(Node prev, int value, Node next) {
this.prev = prev;
this.value = value;
this.next = next;
}
}
private Node head; //头哨兵
private Node tail; //尾哨兵
public DoublyLinkedList() {
this.head = new Node(null, 666, null); //哨兵value无所谓
this.tail = new Node(null, 888, null);
head.next = tail;
tail.prev = head;
}
2 按索引插入
private Node findNode(int index) {
Node p = head;
int i = -1;
while (p != tail) {
if (index == i) return p;
p = p.next;
i++;
}
return null;
}
public void insert(int index, int value) {
Node prev = findNode(index - 1);
if (prev == null) {
throw new IllegalArgumentException(String.format("index [%d] 不合法", index));
}
Node next = prev.next;
Node inserted = new Node(prev, value, next);
prev.next = inserted;
next.prev = inserted;
}
3 头插法
public void addFirst(int value) {
insert(0, value);
}
4 尾插法
public void addLast(int value) {
Node last = tail.prev;
Node added = new Node(last, value, tail);
last.next = added;
tail.prev = added;
}
5 根据索引删除元素
public void remove(int index) {
Node prev = findNode(index - 1);
Node removed = prev.next;
if (removed == tail) {
throw new IllegalArgumentException(String.format("index [%d] 不合法", index));
}
Node next = removed.next;
prev.next = next;
next.prev = prev;
}
6 删除第一个元素
public void removeFirst() {
remove(0);
}
7 删除最后一个元素
public void removeLast() {
Node removed = tail.prev;
if (removed == head) {
throw new IllegalArgumentException(String.format("remove 不合法"));
}
Node last = removed.prev;
last.next = tail;
tail.prev = last;
}
8 遍历
@Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
Node p = head.next;
@Override
public boolean hasNext() {
return p != tail;
}
@Override
public Integer next() {
int value = p.value;
p = p.next;
return value;
}
};
}
双向循环链表:
双向循环列表:首尾相连的双向链表。
1 定义
private class Node {
private Node prev;
private int value;
private Node next;
public Node(Node prev, int value, Node next) {
this.prev = prev;
this.value = value;
this.next = next;
}
}
private Node sentinel = new Node(null, -1, null);
public LoopedDoublyLinkedList() {
sentinel.next = sentinel;
sentinel.prev = sentinel;
}
2 头插法
public void addFirst(int value) {
Node a = sentinel;
Node b = sentinel.next;
Node added = new Node(a, value, b);
a.next = added;
b.prev = added;
}
3 尾插法
public void addLast(int value) {
Node a = sentinel.prev;
Node b = sentinel;
Node added = new Node(a, value, b);
a.next = added;
b.prev = added;
}
4 遍历
@Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
Node p = sentinel.next;
@Override
public boolean hasNext() {
return p != sentinel;
}
@Override
public Integer next() {
int value = p.value;
p = p.next;
return value;
}
};
}
5 删除第一个元素
public void removeFirst() {
Node removed = sentinel.next;
if (removed == sentinel) {
throw new IllegalArgumentException("非法");
}
Node a = sentinel;
Node b = removed.next;
a.next = b;
b.prev = a;
}
6 删除最后一个元素
public void removeLast() {
Node removed = sentinel.prev;
if (removed == sentinel) {
throw new IllegalArgumentException("非法");
}
Node a = removed.prev;
Node b = sentinel;
a.next = b;
b.prev = a;
}
7 按值删除元素
public void removeByValue(int value) {
Node removed = findByValue(value);
if (removed == null) return;
Node a = removed.prev;
Node b = removed.next;
a.next = b;
b.prev = a;
}
private Node findByValue(int value) {
Node p = sentinel.next;
while (p != sentinel) {
if (p.value == value) return p;
p = p.next;
}
return null;
}