## 双链表 从单链表的结构上来看 - 访问特定结点的前驱结点需要遍历整个单链表,移动指针,时间复杂度为:O(n) - 访问特定结点的后继结点只需要移动一次指针,时间复杂度为:O(1) 双链表的引入,很好的解决单链表访问前驱结点时间消耗大的问题。 双链表结点由三部分组成: - `数据域` 存放数据信息 - `prior指针域` 指向结点的前驱结点 - `next指针域` 指向结点的后继结点 ```C++ // 双链表结点类型 typedef struct DNode{ ElemType data; // 结点的数据域 struct DNode *prior; // 结点的前驱指针 struct DNode *next; // 结点的后继指针 }DNode, *DlinkList; ``` ### 基本特点 - 双链表仅仅在单链表的结点中增加了一个指向结点前驱的`prior`指针; - `按值查找`、`按序号查找`在单链表和双链表上的操作是相同的。 - 和单链表不同,`插入`、`删除`操作除了修改`next`指针域,双链表还需要修改`prior`指针域,确保不断`链`,时间复杂度都为:O(1) ### 插入结点 > 在双链表中p所指的结点之后插入结点s ```C++ // 第一步 s->next=p->next; // 第二步 p->next->prior=s; // 第三步 s->prior=p; // 第四步 p->next=s ``` **第一步和第二步必须再第四步之前**,整体时间复杂度为:O(1) ### 删除结点 > 删除双链表中结点p的后继结点q ```C++ // 第一步 p->next=q->next; // 第二步 q->next->prior=p; // 第三步 free(q); ``` **第一步和第二步顺序可换**,整体时间复杂度为:O(1)