目录
简介:
双向链表的应用:linkedList
双向链表也叫双链表,是链表的一种,它的每个数据 结点 中都有两个 指针 ,分别指向直接后继和直接前驱。 所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。 一般我们都构造双向 循环链表 。
好处:插入、删除的速度比ArrayList扩容来的快的多。
缺点:对于随机访问,查询速度慢
代码简单模拟双向列表(详细注解)
结果图例:
注意:
1.遍历是按照指针指向节点的方式遍历的
2.插入、删除是把指向节点和下节点的指向改变就完成插入和删除了
3.我自己改写的有参构造器,相当于新增功能
package com.gao.test.collection.linkedList;
/**
* @Author lie
* @Description 简单介绍双向链表结构
*/
public class DoubleLinkedList {
public static void main(String[] args) {
//第一节点
Node first = new Node();
//最后节点
Node last = new Node();
/**
* 模拟双向链表
* 创建3个节点数据
*/
//这个相当于在链表尾部添加节点,加进来的节点注意头节点和为节点的位置
// (这个应该封装个方法判断是不是第一个加入,因为简单介绍就不封装了,直接指向了)
Node one = new Node("节点数据1",null,null);
first = one;
Node two = new Node("节点数据2",one,null);
last = two;
Node three = new Node("节点数据3",two,null);
//后面新加的都改变最后指针的位置
last = three;
//正序遍历(第一节点的指针,正向遍历所有节点)
System.out.println("====正序遍历====");
forwardIterator(first);
//倒序遍历(最后节点的指针,倒序遍历所有节点)
System.out.println("====倒序遍历====");
reverseIterator(last);
//2、3节点中间插入(我有参构造器已经考虑进去了,直接传入前后节点,就是中间插入)
Node haha = new Node("哈哈,插入节点",two,three);
//遍历一下
System.out.println("====正序遍历插入后的节点====");
forwardIterator(first);
//删除角标置顶位置的节点
deleteNode(two);
//遍历一下
System.out.println("====正序遍历删除后的节点====");
forwardIterator(first);
}
/**
* 删除节点
* @param index 节点位置
*/
private static void deleteNode(Node index) {
//存储一下当前节点的值
final Object item = index.item;
final Node prev = index.pre;
final Node next = index.next;
//前一个节点的next连接到下一个节点上(这里不判断pre、next为空的情况,想看可以追原码看)
prev.next = next;
index.pre = null; //指向空
//后一个节点的pre连接到前一个节点上(这里不判断pre、next为空的情况,想看可以追原码看)
next.pre = prev;
index.next = null; //指向空
index.item = null; //把数据置空,gc处理掉垃圾数据
}
/**
* 正向遍历的方法
* @param first 第一节点
*/
private static void forwardIterator(Node first) {
while (null != first) {
System.out.println(first);
first = first.next;
}
}
/**
* 反向遍历的方法
* @param last 最后节点
*/
private static void reverseIterator(Node last) {
while (null != last) {
System.out.println(last);
last = last.pre;
}
}
}
class Node{
/**
* 存储节点数据
*/
public Object item;
/**
* 链表的前一个节点
*/
public Node pre;
/**
* 链表的下一个节点
*/
public Node next;
public Node() {
}
/**
* 有参构造器(添加节点)
* @param item object
*/
public Node(Object item,Node pre,Node next) {
this.item = item;
//链前面节点
this.pre = pre;
//连接后面节点
this.next = next;
//如果不为空,说明有前面的节点(说明是中间或者是尾部插入操作),把前面节点的next连接这个新增的节点
if(null != pre){
pre.next = this;
}
//如果不为空,说明有后面的节点(说明是中间或者头部插入操作),把后面节点的pre连接这个新增的节点
if (null != next) { next.pre = this;
}
}
@Override
public String toString() {
return item.toString();
}
}
说明:
简单模拟双向列表,健壮性不足,最好可以直接新建linkedList对象,追源码看。