问答题 如何实现双向链表的插入、删除操作
【正确答案】
【答案解析】循环单链表的出现,虽然能够实现从任一结点出发沿着链能找到其前驱结点,但是时间复杂度为O(n)。如果希望从链表中快速确定某一个结点的前驱,另一个解决方法就是在单链表的每个结点里再增加一个指向其前驱的指针域pr。这样形成的链表中就有两条方向不同的链,被称为双向链表(Double Linked List)。双向链表简称双链表,它是由头指针head唯一确定的。带头结点的双链表的某些运算变得方便。将头结点和尾结点链接起来,为双循环链表。
带头结点的双链表的结点结构如图1所示。

图1 带头结点的双向链表

双链表的形式描述:
typedef struct dlistnode
{
DataType data;
struct dlistnode *prior,*next;
}DListNode;
typedef DListNode *DLinkList;
DLinkList head;
由于双链表的对称性,在双链表中能方便地完成各种插入、删除操作。
在双向链表第i个结点P之前插入一个新的结点,则指针的变化情况如图2所示。

图2 双向链表插入操作

具体实现代码如下:
void DInsertBefore()
{
∥在带头结点的双链表中,将值为x的新结点插入*p之前,设p不等于NULL
DListNode*s=malloc(sizeof(DListNode));
s->data=x;
s->prior=p->prior;
s->next=p;
p->prior->next=s;
p->prior=s;
}
双链表上删除结点*p自身的操作如图3所示。