双向链表,也称为双链表,是一种常用的链表数据结构。它的每个节点包含两个指针,一个指向前驱节点,一个指向后继节点。双向链表的优点包括空间复杂度低和容易实现插入和删除操作。
在双向链表中,每个节点都包含两个指针,分别指向前驱节点和后继节点。当我们访问一个节点时,我们可以沿着前驱和后继指针一直遍历到该节点。这使得我们可以方便地访问任意节点,因为我们只需要遍历整个链表一次就可以找到它。
双向链表的空间复杂度比单向链表低,因为它不需要额外的存储空间来存储指向前驱和后继节点的指针。由于其循环性质,双向链表在插入和删除操作时也更加方便和高效。
总之,双向链表是一种非常实用和优雅的链表数据结构,适用于各种场景,如数据库、文件系统和网络编程等。
package com.demo._04双向链表;
import java.util.Iterator;
import java.util.function.Consumer;
/**
* @create 2023/5/4 16:20
* @Desc 双向链表
**/
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, 000, tail);
tail = new Node(null, 111, tail);
head.next = tail ;
tail.prev = head ;
}
/**
* 根据索引位置找到节点
* @param index
* @return
*/
private Node findNode(int index) {
int i = -1;
for (Node p = head ; p != tail; p = p.next, i++){
if(i == index) {
return p;
}
}
return null;
}
/**
* 添加头部元素
* @param value 值
*/
public void addFirst(int value) {
insert(0, value) ;
}
/**
* 删除头部元素
*/
public void removeFirst() {
remove(0) ;
}
/**
* 添加尾元素
* @param value 值
*/
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 illegalArgumentException(0) ;
Node prev = removed.prev;
prev.next = tail;
tail.prev = prev;
}
/**
* 指定索引位置插入
* @param index 索引
* @param value 值
*/
public void insert(int index, int value) {
// 上一个节点
Node prev = findNode(index - 1);
if(prev == null) throw illegalArgumentException(index) ;
// 下一个节点
Node next = prev.next;
Node inserted = new Node(prev, value, next);
prev.next = inserted ;
next.prev = inserted ;
}
/**
* 按元素删除
* @param index 索引
*/
public void remove(int index) {
// 上一个节点
Node prev = findNode(index - 1);
if(prev == null) throw illegalArgumentException(index) ;
// 下一个节点
Node removed = prev.next;
if(removed == tail) throw illegalArgumentException(index) ;
Node next = removed.next;
prev.next = next ;
next.prev = prev ;
}
/**
* 迭代器
* @return
*/
@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 ;
}
};
}
/**
* 异常
* @param index
* @return
*/
private IllegalArgumentException illegalArgumentException(int index) {
return new IllegalArgumentException(String.format("index [%d] 不合法%n", index));
}
public static void main(String[] args) {
// insert test
DoublyLinkedListSentinel list = new DoublyLinkedListSentinel() ;
}
}