1. 双向链表同单向链表一样,同sentinelLinkedList相同的方法,感觉还没有单向链表难。Node 结构 新增prev node,容器外新增tail节点
2. 建议先不要看我写得源码自己手动实现,只将Node内部类复制自己命名得容器内,
实现方法:
a. add方法(添加到头部,尾部添加,指定位置添加)
b. get方法(获取首部,获取尾部,获取指定位置)
c. remove方法(删除首部,删除尾部,删除指定位置)
d. size方法(手动维护一个size变量,实现0(1)复杂度 )
e. 迭代器(实现迭代器,能够循环遍历)
手动实现之后(每个功能只实现一种也可以),再回头参照,思考下即可!
package com.nami.algorithm.study.day04;
import java.io.Serializable;
import java.util.Iterator;
import java.util.function.Consumer;
/**
* 双向链表
* 非线程安全
* beyond u self and trust u self.
*
* @Author: lbc
* @Date: 2023-09-01 9:07
* @email: 594599620@qq.com
* @Description: keep coding
*/
public class DoublyLinkedList<E> implements Serializable, Iterable<E>, Cloneable {
/**
* 容器已添加的元素
*/
private int size = 2;
/**
* 头节点
*/
private Node head;
/**
* 尾部节点
*/
private Node tail;
/**
* 初始化哨兵
*/
public DoublyLinkedList() {
this.head = new Node(null, "head", null);
this.tail = new Node(null, "tail", null);
this.head.next = this.tail;
this.tail.prev = this.head;
}
/**
* 向链表添加数据
*
* @param element 添加的元素
*/
public void addFirst(E element) {
add(0, element);
}
/**
* 向链表尾部添加数据
*
* @param element
*/
public void addLast(E element) {
// Node prev = this.tail.prev;
// Node insertNode = new Node(prev, element, this.tail);
// prev.next = insertNode;
// tail.prev = insertNode;
// ++this.size;
add(size - 2, element);
}
private Node getNode(int index) {
Node p = this.head;
for (int i = -1; p != tail; p = p.next, i++) {
if (i == index) {
return p;
}
}
return null;
}
/**
* 获取容器指定位置的值
*
* @param index
* @return
*/
public E get(int index) {
if (index > size - 2) {
throw new IndexOutOfBoundsException("元素不存在");
}
Node node = getNode(index);
return (E) node.value;
}
/**
* 向元素指定节点添加值
*
* @param index
* @param e
*/
public void add(int index, E e) {
Node prev = getNode(index - 1);
if (prev == null) {
throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", index));
}
Node next = prev.next;
Node insertNode = new Node(prev, e, next);
// 这个好想出来
prev.next = insertNode;
// 此节点调试下就调好了。
next.prev = insertNode;
++this.size;
}
/**
* 移除容器内第一个元素
*/
public void removeFirst() {
remove(0);
}
/**
* 移除容器内指定位置元素
*
* @param index
*/
public void remove(int index) {
if (index > size - 2) {
throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", index));
}
// index =0 返回的是哨兵
Node prev = getNode(index - 1);
if (null == prev) {
throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", index));
}
Node needRemoveNode = prev.next;
if (needRemoveNode == tail) {
throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", index));
}
// 返回删除节点得下一个节点
Node next = needRemoveNode.next;
prev.next = next;
next.prev = prev;
--this.size;
}
/**
* 删除最后一个节点
*/
public void removeLast() {
Node prev = this.tail.prev;
if (prev == this.head) {
return;
}
Node prev1 = prev.prev;
prev1.next = this.tail;
tail.prev = prev1;
--this.size;
}
/**
* 获取容器大小
*
* @return
*/
public int size() {
return this.size - 2;
}
/**
* 迭代器遍历
*
* @return
*/
@Override
public Iterator iterator() {
return new NodeIterator();
}
/**
* 匿名内部类
* 内部类使用到了外部类的成员变量时,不能使用static修饰
*/
private class NodeIterator implements Iterator {
Node node = head.next;
private int nextIndex;
@Override
public boolean hasNext() {
return nextIndex < DoublyLinkedList.this.size - 2;
}
@Override
public Object next() {
Object value = node.value;
node = node.next;
++this.nextIndex;
return value;
}
}
/**
* while实现
*
* @param consumer
*/
public void forEach(Consumer consumer) {
Node firstNode = this.head.next;
while (firstNode != null && firstNode != this.tail) {
consumer.accept(firstNode.value);
firstNode = firstNode.next;
}
}
/**
* Node类型 节点对象
* 二者为组合关系,所以 由外部类变为内部类,对外隐藏实现细节
*/
private static class Node<E> {
/**
* 上一个节点
*/
private Node<E> prev;
/**
* 值
*/
private E value;
/**
* 下一个节点
*/
private Node<E> next;
public Node(Node<E> prev, E value, Node<E> next) {
this.prev = prev;
this.value = value;
this.next = next;
}
}
}