#双向链表
单向链表相对数组来说已经有很多优点了,但是,它还有一个最大的弊端,那就是在某种程度上和深度优先遍历有通性.一条路走到黑,从不回头!这种特性在进行数据操作时,会大大浪费时间,鉴于此,出现了双向链表的概念。
顾名思义,双向链表就是具备两个方向的指向,无非就是每个结点成了两个指针。
每次在插入或删除某个节点时, 需要处理四个节点的引用, 而不是两个. 也就是实现起来要困难一些 . 一个节点既有向前连接的引用, 也有一个向后连接的引用.
创建结点
//定义结点
typedef struct Node{
ElemType data;
struct Node *prior;
struct Node *next;
}Node;
typedef struct Node * LinkList;
• 创建双向链表
- 初始化头结点信息*L的前驱以及后继
- 创建新的临时节点
- 为新增的节点建立依赖关系
/* 双向链表的创建 */
Status creatDoubleLinkList(linkList * L){
*L = (linkList)malloc(sizeof(Node));
if (*L == NULL) return ERROR ;
(*L)->data = -1 ;
(*L)->prior = NULL;
(*L)->next = NULL;
/* 新增数据 */
linkList p = *L ;
for (int i = 0; i<10; i++) {
/* 创建临时结点 */
linkList temp = (linkList)malloc(sizeof(Node));
if (temp == NULL) return ERROR;
temp->data = i ;
temp->prior = NULL ;
temp->next = NULL;
/* 建立依赖关系 */
p->next = temp;
temp->prior = p ;
p = p->next;
}
return OK;
}
• 插入
- 边界条件的判断
- 新建结点temp,对它进行赋值prior\next = NULL data = data
- 方便书写。新建一个LinkList p = *L;
- 找到需要插入数据的前一个位置
- 判断插入的位置是否是链表的尾部
- 尾部和非尾部的两种处理
- 非尾部插入
7.1 把需要插入节点的节点的prior指向新创建的节点 p->next->prior = temp;
7.2 将temp的next指向 要插入的位置的节点,temp->next = p->next;
7.3 将原来的p->next指向新创建的节点temp p->next = temp;
7.4 新创建的节点temp的前驱更新为片
(1、2的先后顺序可以互换,3、4的执行顺序也可以互换,但是必须要保证12在34之前执行,防止丢掉后面的节点)