单链表结点中只有一个指向其后继指针,使得单链表只能从头结点依次顺序的向后遍历。要访问某个节点的前驱结点(插入、删除操作时),只能从头开始遍历,访问后继结点的时间复杂度为O(1),访问前驱结点的时间复杂度为O(n)
为了克服单链表上的上述缺点,引入了双链表,双链表结点中有两个指针prior和next,分别指向其前驱结点和后继结点
双链表中结点类型描述如下:
typedef struct DNode{
//定义双链表的结点类型
ElemType data;//数据域
struct DNode *prior,*next;//前驱和后继指针
}DNode,*DLinklist;
双链表仅在单链表的定义上增加了一个前驱指针prior,因此在双链表中执行按值查找和按位查找的操作与在单链表中相同。但双链表在插入和删除操作的实现上,与单链表有着较大的不同,这是因为“链”变化时也需要对prior指针做出修改,其关键是保证在修改的过程中不断链,此外,双链表还可以很方便的找到其前驱结点,因此,插入、删除结点的算法时间复杂度仅为O(1)
双链表的插入操作
在双链表中p所指的结点之后插入结点*s
插入操作的代码如下:
s->next=p->next;//将结点的*s插入到结点*p之后
p->next->prior=s;
s->prior=p;
p->next=s;
双链表的删除操作
删除双链表中结点*p的后继节点*q;
删除操作的代码片段如下:
p->next=q->next;
q->next->prior=p;
free(q);