双向链表
双向链表
- prior 前驱
- data 数据域
- next 后继

typedef struct Node{
ElementType data;
struct Node *prior;
sturct Node *next;
}Node;
typedef struct Node *LinkList;
1.双向链表的创建
Status createLinkList(LinkList *L){
*L = (LinkList)malloc(sizeof(Node));
if(*L == NULL) return ERROR;
//1 要先将头结点置空并将数据设为-1
(*L)->prior = NULL;
(*L)->next = NULL;
(*L)->data = -1;
//2 新增结点 (使用尾插法)
LinkList p = *L;
for(int i=0;i < 10;i++){
//1 创建结点temp
LinkList temp = (LinkList)malloc(sizeof(Node));
if(temp == NULL) return ERROR;
temp -> prior = NULL;
temp -> next = NULL;
temp -> data = i;
//2 temp 创建双向链表的关系
p->next = temp;
temp ->prior = p;
p = p->next;
}
}
//展示
void display(LinkList L){
LinkList temp = L->next; //跳过为空的头结点
if(temp == NULL){
printf("打印的双向链表为空\n");
return;
}
while(temp){
printf("%d ",temp->data);
temp = temp->next;
}
printf("\n");
}
2.双向链表的插入

4个步骤
- 先找到要插入的前一个结点,B的前驱指向CC
- CC的后继指向B
- A的后继指向CC
- CC的前驱指向A 三步四步可以调换顺序

//L 链表 i 位置 data 数据
Status ListInsert(LinkList *L,int i,ElementType data){
//1 不可以插在头结点前
if(i < 1) return ERROR;
//2 新建结点
LinkList temp = (LinkList)malloc(sizeof(Node));
temp->data = data;
temp->next = NULL;
temp->prior = NULL;
//3
LinkList p = (*L);
//插入位置的前一个位置
for(int j=1;j < i && p;j++){ //找位置 p越界就会for循环break
p=p->next;
}
//4. 如果i超过链表长度 p会指向null
if(p == NULL) return ERROR;
// 5 结点插入到链表中
if(p->next == NULL){ //插入到链表最后一个结点
p->next = temp;
temp -> prior = p;
}else{
p->next->prior = temp;
temp->next = p->next;
p->next = temp;
temp->prior = p;
}
return OK;
}
3.双向链表的删除

- 创建临时指针指向要删除的结点
- A结点的后继指向C
- C的前驱指向A
- 释放B
//指定位置 L 链表 i删除的位置 e 要带回删掉的结点的数据
Status ListDelete(LinkList *L,int i,ElementType *e){
int k =1;
LinkList p = (*L);
if(*L == NULL) return ERROR;
while(k<i&& p!=NULL){
p = p->next;
k++;
}
if(k>i && p== NULL) return ERROR; //如果i输入的不合法
LinkList delTemp = p->next;
*e = delTemp->data;
p->next = delTemp ->next;
if(delTemp->next!=NULL){ //不是尾结点的情况下
delTemp->next->prior = p;
}
free(delTemp);
return OK;
}
//根据指定结点的数据来删除结点
Status LinkListDeleteVal(LinkList *L,int data){
LinkList p = (*L)->next;
while(p){
if(p->data == data){
p->prior ->next = p->next;
if(p->next != NULL){
p->next->prior = p->prior;
}
free(p);
break;
}
p = p->next;
}
return OK;
}
4.双向链表的查找
//查找
int selectElem(LinkList L,ElementType elem){
LinkList p = L->next;
int i = 1;
while (p) {
if (p->data == elem) {
return i;
}
i++;
p = p->next;
}
return -1;
}
5.双向链表的替换
//更新
Status replaceLinkList(LinkList *L,int index,ElemType newElem){
LinkList p = (*L)->next;
for (int i = 1; i < index; i++) {
p = p->next;
}
p->data = newElem;
return OK;
}
双向循环链表

1.双向循环链表的创建
Status initLinkList(LinkeList *L){
*L = (LinkList)malloc(sizeof(Node));
if(*L == NULL) return ERROR;
(*L)->next = (*L);
(*L)->prior = (*L);
(*L)->data = -1;
return OK;
}
2.双向循环链表的插入
//需要判断是否为尾,但是不需要判断是否是头
Status LinkListInsert(LinkList *L,int index,ElemType e){
LinkList p = *L;
int i = 1;
if(*L == NULL) return ERROR; //如果要插入的为空就报错
while(i < index){
p = p->next;
i++;
}
if(i > index) return ERROR;
LinkList temp = (LinkList)malloc(sizeof(Node));
if(temp == NULL) return ERROR;
temp ->data = e;
temp->prior = p;
temp->next = p->next;
p->next = temp;
if(*L != temp->next){ //如果不是最后一个结点
temp ->next ->prior = temp;
}
}
3.双向循环链表的删除
逻辑上与双向链表的删除相同,所以可以借鉴
Status LinkListDelete(LinkList *L,int index,ElemType *e){
int i=1;
if(*L == NULL){
return ERROR;
}
LinkList temp = (*L) ->next;
if(temp->next == *L){//如果只剩下一个结点
free(*L);
*L == NULL;
return OK;
}
while(i < index){
temp = temp->next;
i++;
}
*e = temp->data;
temp ->prior ->next = temp->next;
temp->next->prior = temp->prior;
free(temp);
return OK;
}
4.双向循环链表的查找
5.双向循环链表的替换
其他 上一节课的引申
- 如何判断链表是否有环