准备条件
#define ERROR 0#define TRUE 1#define FALSE 0#define OK 1#define MAXSIZE 20 /* 存储空间初始分配量 */typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */typedef int ElemType;/* ElemType类型根据实际情况而定,这里假设为int *///定义结点typedef struct Node{ElemType data;struct Node *prior;struct Node *next;}Node;typedef struct Node * LinkList;
双向链表学习
双向链表创建

代码实现:
//5.1 创建双向链接Status createLinkList(LinkList *L){//*L 指向头结点*L = (LinkList)malloc(sizeof(Node));if (*L == NULL) return ERROR;(*L)->prior = NULL;(*L)->next = NULL;(*L)->data = -1;//新增数据LinkList p = *L;for(int i=0; i < 10;i++){//1.创建1个临时的结点LinkList temp = (LinkList)malloc(sizeof(Node));temp->prior = NULL;temp->next = NULL;temp->data = i;//2.为新增的结点建立双向链表关系//① temp 是p的后继p->next = temp;//② temp 的前驱是ptemp->prior = p;//③ p 要记录最后的结点的位置,方便下一次插入p = p->next;}return OK;}
打印链表:**
//5.2 打印循环链表的元素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");}
双向链表插入


代码实现:
//5.3 双向链表插入元素Status ListInsert(LinkList *L, int i, ElemType data){//1. 插入的位置不合法 为0或者为负数if(i < 1) return ERROR;//2. 新建结点LinkList temp = (LinkList)malloc(sizeof(Node));temp->data = data;temp->prior = NULL;temp->next = NULL;//3.将p指向头结点!LinkList p = *L;//4. 找到插入位置i直接的结点for(int j = 1; j < i && p;j++)p = p->next;//5. 如果插入的位置超过链表本身的长度if(p == NULL){return ERROR;}//6. 判断插入位置是否为链表尾部;if (p->next == NULL) {p->next = temp;temp->prior = p;}else{//1️⃣ 将p->next 结点的前驱prior = tempp->next->prior = temp;//2️⃣ 将temp->next 指向原来的p->nexttemp->next = p->next;//3️⃣ p->next 更新成新创建的tempp->next = temp;//4️⃣ 新创建的temp前驱 = ptemp->prior = p;}return OK;}
双向链表删除

代码实现:
//5.4 删除双向链表指定位置上的结点Status ListDelete(LinkList *L, int i, ElemType *e){int k = 1;LinkList p = (*L);//1.判断双向链表是否为空,如果为空则返回ERROR;if (*L == NULL) {return ERROR;}//2. 将指针p移动到删除元素位置前一个while (k < i && p != NULL) {p = p->next;k++;}//3.如果k>i 或者 p == NULL 则返回ERRORif (k>i || p == NULL) {return ERROR;}//4.创建临时指针delTemp 指向要删除的结点,并将要删除的结点的data 赋值给*e,带回到main函数LinkList delTemp = p->next;*e = delTemp->data;//5. p->next 等于要删除的结点的下一个结点p->next = delTemp->next;//6. 如果删除结点的下一个结点不为空,则将将要删除的下一个结点的前驱指针赋值p;if (delTemp->next != NULL) {delTemp->next->prior = p;}//7.删除delTemp结点free(delTemp);return OK;}
双向链表删除指定的元素

代码实现:
//5.5 删除双向链表指定的元素Status LinkListDeletVAL(LinkList *L, int data){LinkList p = *L;//1.遍历双向循环链表while (p) {//2.判断当前结点的数据域和data是否相等,若相等则删除该结点if (p->data == data) {//修改被删除结点的前驱结点的后继指针,参考图上步骤1️⃣p->prior->next = p->next;//修改被删除结点的后继结点的前驱指针,参考图上步骤2️⃣if(p->next != NULL){p->next->prior = p->prior;}//释放被删除结点pfree(p);//退出循环break;}//没有找到该结点,则继续移动指针pp = p->next;}return OK;}
双向链表查找元素
int selectElem(LinkList L,ElemType elem){LinkList p = L->next;int i = 1;while (p) {if (p->data == elem) {return i;}i++;p = p->next;}return -1;}
双向链表更新结点
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;}
双向循环链表学习
双向循环链表

代码实现:
//6.1 双向循环链表初始化Status creatLinkList(LinkList *L){*L = (LinkList)malloc(sizeof(Node));if (*L == NULL) {return ERROR;}(*L)->next = (*L);(*L)->prior = (*L);//新增数据LinkList p = *L;for(int i=0; i < 10;i++){//1.创建1个临时的结点LinkList temp = (LinkList)malloc(sizeof(Node));temp->data = i;//2.为新增的结点建立双向链表关系//① temp 是p的后继p->next = temp;//② temp 的前驱是ptemp->prior = p;//③ temp的后继是*Ltemp->next = (*L);//④ p 的前驱是新建的tempp->prior = temp;//⑤ p 要记录最后的结点的位置,方便下一次插入p = p->next;}return OK;}
双向循环列表插入结点

代码实现:
//6.2 双向循环链表插入元素/*当插入位置超过链表长度则插入到链表末尾*/Status LinkListInsert(LinkList *L, int index, ElemType e){//1. 创建指针p,指向双向链表头LinkList p = (*L);int i = 1;//2.双向循环链表为空,则返回errorif(*L == NULL) return ERROR;//3.找到插入前一个位置上的结点pwhile (i < index && p->next != *L) {p = p->next;i++;}//4.如果i>index 则返回errorif (i > index) return ERROR;//5.创建新结点tempLinkList temp = (LinkList)malloc(sizeof(Node));//6.temp 结点为空,则返回errorif (temp == NULL) return ERROR;//7.将生成的新结点temp数据域赋值e.temp->data = e;//8.将结点temp 的前驱结点为p;temp->prior = p;//9.temp的后继结点指向p->next;temp->next = p->next;//10.p的后继结点为新结点temp;p->next = temp;//如果temp 结点不是最后一个结点if (*L != temp->next) {//11.temp节点的下一个结点的前驱为temp 结点temp->next->prior = temp;}else{(*L)->prior = temp;}return OK;}
打印表信息:
//6.3 遍历双向循环链表Status Display(LinkList L){if (L == NULL) {printf("打印的双向循环链表为空!\n\n");return ERROR;}printf("双向循环链表内容: ");LinkList p = L->next;while (p != L) {printf("%d ",p->data);p = p->next;}printf("\n\n");return OK;}
双向循环列表删除结点

代码实现:
//6.4 双向循环链表删除结点Status LinkListDelete(LinkList *L,int index,ElemType *e){int i = 1;LinkList temp = (*L)->next;if (*L == NULL) {return ERROR;}//①.如果删除到只剩下首元结点了,则直接将*L置空;if(temp->next == *L){free(*L);(*L) = NULL;return OK;}//1.找到要删除的结点while (i < index) {temp = temp->next;i++;}//2.给e赋值要删除结点的数据域*e = temp->data;//3.修改被删除结点的前驱结点的后继指针 图1️⃣temp->prior->next = temp->next;//4.修改被删除结点的后继结点的前驱指针 图2️⃣temp->next->prior = temp->prior;//5. 删除结点tempfree(temp);return OK;}
顺序表和链表的比较
线性表总结


