链表是一种非连续、非顺序的存储结构
双向链表与单向链表的区别在于,双向链表的节点可以查找上一节点和下一节点称为双向,而单向链表只能查找下一节点称为单向
双向链表在java中的实现
1.创建节点类
public static class Node<E>{
/** 前驱 */
private Node prev;
/** 数据 */
private E e;
/** 后继 */
private Node next;
public Node(Node prev, E e, Node next) {
this.prev = prev;
this.e = e;
this.next = next;
}
}
Node节点类中有三个属性,分别为前驱prev、数据泛型e、后继next
2.实现双向链表
private Node first;
private Node last;
private int size;
/**
* 添加
* @param e
*/
public void add(E e){
addLast(e);
}
/**
* 尾部添加
*/
private void addLast(E e) {
//新节点
Node<E> target = new Node<>(last, e, null);
//获取尾节点
Node<E> mLast = last;
//尾节点指向新节点
last = target;
//链表为空时,first指向新节点,不为空时,将之前的尾节点后继指向新节点
if (first == null){
first = target;
}else {
mLast.next = target;
}
//长度+1
size++;
}
或是根据下标插入数据
/**
* 在index位置添加
* @param index
* @param e
*/
public void add(int index, E e){
if (index > size || index < 0){
return;
}
//尾部添加
if (index == size){
addLast(e);
return;
}
//找到当前index位置的节点
Node<E> node = node(index);
//当前节点的前驱
Node<E> prev = node.prev;
//要插入的新节点
Node<E> target = new Node<>(prev, e, node);
if (prev == null){
//插入头部
first = target;
node.prev = target;
}else {
prev.next = target;
node.prev = target;
}
size ++;
}
图示:
删除操作:
/**
* 删除
* @return
*/
public E remove(){
return removeLast();
}
/**
* 尾部删除
* @return
*/
private E removeLast() {
if (last == null){
return null;
}
Node<E> mLast = last;
Node<E> prev = last.prev;
if (mLast.prev == null){
//只有一个
first = null;
last = null;
}else {
prev.next = null;
last = last.prev;
}
size--;
return mLast.e;
}
尾部删除直接将last指向尾部节点的前驱,然后把前驱的后继置为null
/**
* 删除
*/
public E remove(int index){
if (index >= size || index<0){
return null;
}
if (index == (size-1)){
return removeLast();
}
Node<E> node = node(index);
Node<E> prev = node.prev;
Node<E> next = node.next;
if (prev == null){
first = next;
next.prev = null;
}else {
prev.next = node.next;
next.prev = node.prev;
}
size--;
return node.e;
}
删除图示:
查看源码==========》完整类LinkList