一 概述
在单链表中只有一个指向后继结点的指针,使得单链表只能从头结点依次顺序地向后遍历。要访问某个结点的前驱结点(插入,删除操作时),只能从头开始遍历,访问后继结点的时间复杂度为O(1),访问前驱结点的时间复杂度为O(n)。
双向链表的结点中存在两个指针prior和next,分别指向其前驱结点和后继结点。
二 双链表中结点类型代码实例
typedef struct DNode{ //定义双链表结点的结构体类型
ElemType data; //定义双链表结点数据域类型
struct DNode *prior,*next; //定义结点前驱和后继指针
}DNode,*DLinkList;
三 双链表特点分析
双链表在单链表的结点中增加了一个指向其前驱的prior指针,因此双链表中的按值查找和按位查找的操作同单链表一致。但是双链表在插入和删除操作的实现上的不同在于“链”变化时需要对prior指针做出修改,其关键时保证在修改的过程中链表不会断开。于此同时,双链表可以很方便地找到其前驱结点,因此,插入和删除操作的时间复杂度为O(1)。
四 双链表的拆入操作
如果在双链表中p所指的结点之后插入结点*s,插入过程如图所示:
插入过程的代码实例如下:
//将结点*s插入到结点*p之后
1. s->next = p->next;
2. p->next->prior = s;
3. p->next = s;
4. s->prior = p;
注意:在此过程中,涉及到语句顺序的问题,我们在插入数据之前应该先将插入点的指针重新赋值,即可理解为先断链。所以要求先执行1和2,然后执行3和4。如果先执行3和4则指针p->next会丢失。如果p所指的结点为最后一个结点,则直接执行3和4即可。
五 双链表的删除操作
如果删除双链表中结点*p的后继结点*q,删除过程如图所示:
删除过程的代码实例如下:
//将双链表中的q结点删除
1. p->next = q->next;
2. q->next->prior = p;
3. free(q);//释放结点空间
注意:如果*q结点为双链表的最后一个结点,则p->next = NULL;q->prior = NULL;free(q);