双向链表(带哨兵)
通过添加头尾哨兵head、tail,达到双向链表的目的
函数
功能
- 根据索引查找节点->findNode(index : int) : Node
插入
- 根据索引插入->insert(index : int,value : int) : void删除-
- 从尾插入->addLast(value : int) : void
删除
- 根据索引删除->remve(index : int) : void
- 从尾删除->removeLast():void
遍历
- 迭代器iterator() : Iterator<Integer>
代码
import java.util.Iterator;
/**
* 双向链表(带哨兵)
*/
public class DoublyLinkedListSentinel implements Iterable<Integer> {
static class Node {
Node prev; // 上一个节点指针
int value; // 值
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 DoublyLinkedListSentinel() {
head = new Node(null, 666, null);
tail = new Node(null, 888, null);
head.next = tail;
tail.prev = head;
}
Node findNode(int index) {
int i = -1;
for (Node p = head; p != tail; p = p.next, i++) {
if (i == index) {
return p;
}
}
return null;
}
public void addFirst(int value) {
insert(0, value);
}
public void removeFirst() {
remove(0);
}
public void addLast(int value) {
Node last = tail.prev;
Node added = new Node(last, value, tail);
last.next = added;
tail.prev = added;
}
public void removeLast() {
Node removed = tail.prev;
if (removed == head) {
throw illegalIndex(0);
}
Node prev = removed.prev;
prev.next = tail;
tail.prev = prev;
}
public void insert(int index, int value) {
Node prev = findNode(index - 1);
if (prev == null) {
throw illegalIndex(index);
}
Node next = prev.next;
Node inserted = new Node(prev, value, next);
prev.next = inserted;
next.prev = inserted;
}
public void remove(int index) {
Node prev = findNode(index - 1);
if (prev == null) {
throw illegalIndex(index);
}
Node removed = prev.next;
if (removed == tail) {
throw illegalIndex(index);
}
Node next = removed.next;
prev.next = next;
next.prev = prev;
}
private IllegalArgumentException illegalIndex(int index) {
return new IllegalArgumentException(
String.format("index [%d] 不合法%n", index));
}
@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;
}
};
}
}
双向环形链表(带哨兵)
在双向循环链表中,哨兵即做头又做尾,构成循环。
函数
添加
- 添加到头->addFirst(value : int) : void
- 添加到尾->addLast(value : int) : void
删除
- 删除头->removeFirst() : void
- 删除尾->removeLast() : void
- 根据值删除->removeByValue(value : int) : void
遍历
- 迭代器
工具
- 根据值寻找节点->findByValue(value : int) : Node
代码
import java.util.Iterator;
/**
* 环形链表
*/
public class DoublyLinkedListSentinel implements Iterable<Integer> {
@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;
}
};
}
private static class Node {
Node prev;
int value;
Node next;
public Node(Node prev, int value, Node next) {
this.prev = prev;
this.value = value;
this.next = next;
}
}
private final Node sentinel = new Node(null, -1, null);
public DoublyLinkedListSentinel() {
sentinel.prev = sentinel;
sentinel.next = sentinel;
}
/**
* 添加到第一个
*
* @param value 待添加值
*/
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;
}
/**
* 添加到最后一个
*
* @param value 待添加值
*/
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;
}
/**
* 删除第一个
*/
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;
}
/**
* 删除最后一个
*/
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;
}
/**
* 根据值删除
*
* @param value 目标值
*/
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;
}
private Node findNode(int index){
int i = 0;
for(Node p = sentinel.next; p != sentinel;p = p.next,i++){
if(i == index){
return p;
}
}
return null;
}
public void insert(int index,int value){
Node p = findNode(index);
if(p == null) throw new IllegalArgumentException("错误");
Node a = p.prev;
Node b = p.next ;
Node added = new Node(a,value,b);
a.next = added;
b.prev = added;
}
}
补充
单链表的递归遍历,利用Java的 Consumer
接口来实现对链表中每个节点执行特定操作。
代码
public void loop3(Consumer<Integer> before,
Consumer<Integer> after) {
recursion(head, before, after);
}
private void recursion(Node curr,
Consumer<Integer> before, Consumer<Integer> after) { // 某个节点要进行的操作
if (curr == null) {
return;
}
before.accept(curr.value);
recursion(curr.next, before, after);
after.accept(curr.value);
}
来源
路漫漫其修远兮,吾将上下而求索。