【为什么设计双向链表】
在单链表中,有了next指针,我们查找下一个结点的复杂度为O(1),但是如果要查找上一个结点,最坏的时间复杂度就是O(n)了,因为每次都需要从头开始遍历查找。
【双线链表(Double Linked List)】
双向链表是在单链表的每个结点中,在设置一个指向其前驱结点的指针域。所以在双向链表中的每个结点都有两个指针域,一个指向其后继,一个指向其前驱。
[ 与单链表相同的操作 ]
双向链表是单链表中扩展出来的结构,所以很多操作都和单链表相同,例如:求长度的size()、查找元素的get(index)、获得元素位置的Locate(E),这些操作只涉及一个方向的指针。
[ 与单链表不用的操作 ]
在插入和删除时,需要更改两个指针变量。
【插入操作】
假设插入数据域为 e 的结点为 s ,实现将 s 插入到结点 p 和结点 p.next 之间。
[ 插入步骤 ]:(其中1,2两步可以调换顺序,3,4步骤不可乱)
/**1. 把p 赋值给s 的前驱。**/ s.prior=p;
/**2. 把p的后继p.next 赋值给 s的后继s->next。**/ s.next=p.next;
/**3. 把s 赋值给 p的后继p.next的前驱 p.next.prior**/ p.next.prior=s; //即:使p.next的前驱指针指向要插入的s结点
/**4. 把s 赋值给 p的后继p.next 。**/ p.next=s; //即:使p的后继指针指向要插入的s结点
【删除操作】
假设要删除的结点为P,显然能获取其前驱p.prior和后继p.next
[ 删除步骤 ]
/**1.把p的后继p.next 赋值给 p的前驱的后继p.prior.next **/ p.prior.next= p.next; /**2.把p的前驱p.prior赋值给 p的后继的前驱p.next.prior**/ p.next.prior= p.prior;
/**3.清空其前驱指针、后继指针、数据域**/
p.next=null;
p.prior=null;
p.obj=null;