1.概述
在单链表中,每个结点只有一个指向后继结点的链。若要查找某个结点的前驱结点,则需要从链表的头指针开始沿着链表方向逐个查找,效率很低。此时,就需要采用双链表。
2.双链表结构
双链表(double linked list)的每个结点有两个链域,分别指向它的前驱和后继结点,结构如下:
当head.next = null时,双链表为空
设p指向双链表中非两端的某个结点,则下列关系成立
p = p.next.prev = p.prev.next
3.插入元素
在p结点之前插入结点q,如下:、
q = new DLinkNode(x);
q.prev = p.prev;//p的前驱结点信息,即插入之后q的前驱结点信息,原生态保留
q.next = p;//q的后继结点,即p。现在q结点的前驱和后继结点都指明了,下来就要指明p结点对于其前驱和后继结点的关系
p.prev.next = q;//指明q的前驱结点的后继结点是q
p.prev = q;//指明q的后继结点的前驱结点是q
4.删除元素
删除p结点,只需要改变p结点相当于其前驱和后继结点的关系即可,即p的前驱结点不在指明它的后继结点是p,p的后继结点不在指明它的前驱结点是p,程序如下:
p.prev.next = p.next;
if(p.next!=null){
p.next.prev = p.prev;
}
5.循环双链表
与循环单链表相似,只不过需多考虑其前驱结点而已
当head.next == head且head.prev == head时,循环双链表为空。
6.双链表类
双链表结点类的声明与单链表结点类(点击打开链接)的类似,只不过多出一个prev成员变量而已,其构造方法相应的改变即可;同理,双链表类的操作也和单链表类(点击打开链接)的操作相类似,同样多考虑一下前驱结点即可。