链表的概念
定义:链表是一种物理存储上非连续,数据元素的逻辑顺序通过链表中的指针链接次序,实 现的一种线性存储结构(顺序存取)
特点:链表由一系列节点(链表中每一个元素称为节点)组成,节点在运行时动态生成 (malloc),每个节点包括两个部分:
(1)存储数据元素的数据域
(2)存储下一个节点首地址的指针域
eg:
1,3,5,7,9
存储数据元素 1
1 数据要存储 int (数据)
&3 下一个元素的地址 * (关系)存储数据元素 3
3 数据要存储 int (数据)
&5 下一个元素的地址 * (关系)
....
链表与数组的对比 (以带头结点的双向循环链表为例)
链表是通过节点把离散的数据链接成一个表,通过对节点的插入和删除操作从而实现对数据的存取。而数组是通过开辟一段连续的内存来存储数据,这是数组和链表最大的区别。数组的每个成员对应链表的节点,成员和节点的数据类型可以是标准的 C 类型或者是 用户自定义的结构体。数组有起始地址和结束地址,而链表是一个圈,没有头和尾之分, 但是为了方便节点的插入和删除操作会人为的规定一个根节点(头节点)
无头结点单链表
LinkedList.h
#ifndef __LINKEDLIST_H__ #define __LINKEDLIST_H__ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> typedef int ElemType; struct node { ElemType data; // 数据域 保存数据 struct node *next; // 指针域 保存逻辑上的下一个(关系) }; extern struct node* create_list(); // 创建一个新链表,返回链表的首地址 extern struct node* insert_node_order(struct node* h, ElemType d); // 有序插入 extern struct node* create_sort_list(); // 创建一个有序新链表,返回链表的首地址 extern void print_list(struct node* h); // 遍历遍历 /* add_a_node:在链表h中值为x的结点前面,增加一个结点 该结点的值为a,然后返回链表的首地址。 假设没有值为x的结点,则在尾部增加。如果有多个值为x 的结点则增加在第一个值为x的结点前面。 */ extern struct node* add_a_node(struct node *h, ElemType x, ElemType a); extern struct node* delete_node(struct node *h, ElemType x); // 在h指向的链表中,删除值为x的结点 extern void update_node(struct node *h, ElemType x, ElemType a); // 把链表中值为x的结点的值改成a extern struct node* destroy_list(struct node *h); // 销毁链表 extern struct node* reverse_list(struct node *h); // 逆置单链表 extern int get_count_node(struct node *h); // 获取结点的个数 extern bool GetElem(struct node *h, int pos, ElemType *val); // 得到第i个元素的值 extern bool ListEmpty(struct node *h); // 判断链表是否为空 extern struct node* sort_list_with_no_head(struct node *h); // 对单链表进行排序 extern struct node* LocateElem1(struct node *h, ElemType e); // 按值查找,返回地址 extern int LocateElem2(struct node *h, ElemType e); // 按值查找,返回位置序号 extern struct node* insert_node(struct node *h, int i, ElemType e); // 插入——在第i个结点前插入一个值为e的新结点 extern struct node* delete_a_node(struct node *h, int i, ElemType *e); // 删除第i个结点 #endif
LinkedList.c
#include "LinkedList.h" /* create_list:创建一个新链表,返回链表的首地址 */ struct node* create_list() { ElemType d; struct node *head = NULL; // 指向链表的首结点 struct node *tail = NULL; // 指向链表的尾结点 struct node *pnew = NULL; // 指向新创建的结点 while (1) { // step1:每保存一个数据,就要创建一个结点(结构体) scanf("%d", &d); if (d == 0) { break; } pnew = malloc(sizeof(*pnew)); // step2:把数据写入到结点中去 pnew->data = d; pnew->next = NULL; // step3:把结点加入到链表中 if (head == NULL) { // 从无到有,首尾结点都是pnew head = pnew; tail = pnew; } else { // 从少到多 // 尾插 #if 1 tail->next = pnew; // tail指向新结点 tail = pnew; // tail被pnew替代 #endif #if 0 // 头插 pnew->next = head; // 新结点指向head head = pnew; // head被pnew替代 #endif } } return head; } // 有序插入 struct node* insert_node_order(struct node *h, ElemType d) { // 创建一个新节点 struct node *pnew = (struct node*)malloc(sizeof(*pnew)); pnew->data = d; pnew->next = NULL; // 插入 /* 比第一个节点要小,头插法 比最后一个结点要大 尾插法 中间插,找第一个比它大的结点 */ if (h == NULL) { h = pnew; } else { struct node *p = h; // 遍历结点 struct node *pre = NULL; // 找第一个比pnew大的结点 while (p) { if (p->data > pnew->data) { break; } pre = p; p = p->next; } if (p == NULL) { // 没有找到比它大 尾插 pre->next = pnew; } else if (p == h) { // 找到的结点为第一个结点 // 头插 pnew->next = h; h = pnew; } else { // 中间插 pnew->next = p; pre->next = pnew; } } return h; } /* create_sort_list:创建一个有序新链表,返回链表的首地址 */ struct node* create_sort_list() { ElemType d; struct node *head = NULL; // 指向链表的首结点 struct node *tail = NULL; // 指向链表的尾结点 struct node *pnew = NULL; // 指向新创建的结点 while (1) { // step1:每保存一个数据,就要创建一个结点(结构体) scanf("%d", &d); if (d == 0) { break; } pnew = malloc(sizeof(*pnew)); // step2:把数据写入到结点中去 pnew->data = d; pnew->next = NULL; // step3:把结点加入到链表中 if (head == NULL) { // 从无到有,首尾结点都是pnew head = pnew; tail = pnew; } else { // 从少到多 struct node *p = head; // 指向链表的首结点,作用找到第一个比新结点大的那个结点 struct node *pre = NULL; // 指向p指向的结点的前一个结点 while (p) { // <==> p != NULL 遍历链表 if (p->data > pnew->data) { // 找位置 break; } else { // 本结点不是,往后走 pre = p; p = p->next; } } if (p != NULL) { // 找到了一个比pnew大的结点 if (p == head) { // 头插 pnew->next = head; head = pnew; } else { // 中间插 pre->next = pnew; pnew->next = p; } } else { // 没找到 尾插 pre->next = pnew; } } } return head; } // 遍历遍历 void print_list(struct node *h) { // 特殊情况 if (h == NULL) { return ; } while (h) { printf("%d ", h->data); h = h->next; } putchar('\n'); } /* add_a_node:在链表h中值为x的结点前面,增加一个结点 该结点的值为a,然后返回链表的首地址。 假设没有值为x的结点,则在尾部增加。如果有多个值为x 的结点则增加在第一个值为x的结点前面。 */ struct node* add_a_node(struct node *h, ElemType x, ElemType a) { // step1:创建一个值为a的新结点 struct node *pnew = malloc(sizeof(*pnew)); pnew->data = a; pnew->next = NULL; // 特殊情况 if (h == NULL) { h = pnew; return h; } struct node *p = h; // 遍历指针 struct node *pre = NULL; // 指向p指向的结点的前一个结点 // step2:找到值为x的结点 while (p) { // while (p != NULL) if (p->data == x) { // 找到了 break; } pre = p; p = p->next; // 没找到,往后走 } // step3:把新结点加入链表中 if (p != NULL) { // 找到了 if (p == h) { //头插 pnew->next = h; h = pnew; } else { // 中间插 // pnew->next = p; // 新结点指向p指向的结点 // pre->next = pnew; // p指向的结点的前一个结点 指向 新结点 pre->next = pnew; pnew->next = p; } } else { // 没找到 pre->next = pnew; // 尾插 } return h; } /* delete_node:在h指向的链表中,删除值为x的结点 */ struct node* delete_node(struct node *h, ElemType x) { // 特殊情况 if (h == NULL) { return h; } struct node *p = h; // 遍历指针 struct node *pre = NULL; // 指向p指向的结点的前一个结点 // step1:找到值为x的结点 while (p) { if (p->data == x) { // 找到了 // step2:删除值为x的结点 if (p == h) { // 删除首结点 h = h->next; p->next = NULL; // 为了工程规范,释放前把结点内的指针指向NULL free(p); p = h; } else { // 删中间、末尾的结点 pre->next = p->next; p->next = NULL; // 为了工程规范,释放前把结点内的指针指向NULL free(p); p = pre->next; // p往后走,pre不动 } } else { // 没找到 往后走 pre = p; p = p->next; } } return h; } /* update_node:把链表中值为x的结点的值改成a */ void update_node(struct node *h, ElemType x, ElemType a) { while (h) { if (h->data == x) { h->data = a; } h = h->next; } } /* 销毁链表 */ struct node* destroy_list(struct node *h) { if (h == NULL) { return h; } struct node *pc = h; // 指向被拆结点 while (pc) { h = h->next; pc->next = NULL; // 为了工程规范,释放前把结点内的指针指向NULL free(pc); pc = h; } return h; } /* 逆置单链表(不能进行额外的申请结点) 1. 直接交换数据域 2. 把原链表的每一个结点 摘下来,然后按照 头插法 插入到新的链表 */ struct node* reverse_list(struct node *h) { struct node *head = NULL; // 保存新链表的首结点 struct node *pc = h; // 指向被拆结点 while (pc) { // 1.把原链表的每一个结点摘下来 h = h->next; pc->next = NULL; // 2.把摘下来的结点 按照头插法 插入 if (head == NULL) { // 从无到有 head = pc; } else { // 头插 pc->next = head; head = pc; } pc = h; // 再摘一个 } return head; } /* 获取结点的个数 1. 递归 2. 遍历 */ int get_count_node(struct node *h) { if (h == NULL) { return 0; } return 1 + get_count_node(h->next); } // 得到第pos个元素的值 bool GetElem(struct node *h, int pos, ElemType *val) { if (h == NULL) { return false; } struct node *p = h; // 遍历指针 int i = 1; while (p) { if (i == pos) { *val = p->data; return true; } i++; p = p->next; } return false; } // 判断链表是否为空 bool ListEmpty(struct node *h) { if (h == NULL) { return true; } return false; } // 对单链表进行排序 struct node* sort_list_with_no_head(struct node *h) { // 1.遍历,将原来链表中的每一个结点依次摘下来 struct node *head = h; // 指向数据结点的第一个结点 struct node *pc = head; // 要摘下来的结点 h = NULL; // 2.将摘下来的结点 插入到新的链表中 while (pc) { // 摘 head = head->next; pc->next = NULL; // 加到链表 if (h == NULL) { // 从无到有 h = pc; } else { // 找第一个比插入结点大的结点p struct node *p = h; // 遍历指针 struct node *pre = NULL; // 指向p指向的那个结点的前一个结点 while (p) { if (p->data > pc->data) { break; } pre = p; p = p->next; } if (p == NULL) { // 没有找到 尾插 pre->next = pc; } else { // 找到了 if (p == h) { // 头插法 pc->next = h; h = pc; } else { // 中间插 pre->next = pc; pc->next = p; } } } pc = head; // 链表的第一个结点就会成为下一个要摘的结点 } return h; } /* 按值查找,返回地址 在链表L中查找值为e的数据元素 找到,则返回L中值为e的数据元素的地址,查找失败返回NULL */ struct node* LocateElem1(struct node *h, ElemType e) { struct node *p = h; // 遍历指针 while (p && p->data != e) { p = p->next; } return p; } /* 按值查找,返回位置序号 在链表L中查找第一个值为e的数据元素 找到,则返回L中值为e的位置序号,查找失败返回0 */ int LocateElem2(struct node *h, ElemType e) { struct node *p = h; // 遍历指针 int j = 1; while (p && p->data != e) { p = p->next; j++; } if (p) { return j; } return 0; } // 插入——在第i个结点前插入一个值为e的新结点 struct node* insert_node(struct node *h, int i, ElemType e) { // 特殊情况 if (h == NULL || i < 1 || i > get_count_node(h)) { return h; } struct node *pnew = malloc(sizeof(*pnew)); // 创建一个新结点 pnew->data = e; pnew->next = NULL; struct node *p = h; // 遍历指针 struct node *pre = NULL; // 遍历指针的前驱结点 int j = 1; while (j != i) { pre = p; p = p->next; j++; } if (j == 1) { // 头插 pnew->next = p; h = p; } else { // 中间插 pre->next = pnew; pnew->next = p; } return h; } // 删除第i个结点 struct node* delete_a_node(struct node *h, int i, ElemType *e) { // 特殊情况 if (h == NULL || i < 1 || i > get_count_node(h)) { return h; } struct node *p = h; // 遍历指针 struct node *pre = NULL; // 遍历指针的前驱结点 int j = 1; while (j != i) { pre = p; p = p->next; j++; } if (j == 1) { // 头删 *e = p->data; // 保存被删除结点数据 h = h->next; p->next = NULL; free(p); } else { // 中间删、尾删 *e = p->data; pre->next = p->next; p->next = NULL; free(p); } return h; }
main.c
#include "LinkedList.h" int main(int argc, char *argv[]) { // struct node *h = create_list(); // 创建一个新链表,返回链表的首地址 struct node *h = create_sort_list(); // 创建一个有序新链表,返回链表的首地址 print_list(h); // 遍历遍历 printf("链表长度为:%d\n", get_count_node(h)); h = add_a_node(h, 3, 999); // 在值为3的结点前面增加一个值为999的结点 print_list(h); // 遍历遍历 printf("链表长度为:%d\n", get_count_node(h)); h = delete_node(h, 999); // 删除值为999的结点 print_list(h); // 遍历遍历 printf("链表长度为:%d\n", get_count_node(h)); update_node(h, 3, 33); // 把链表中值为3的结点的值改成33 print_list(h); // 遍历遍历 printf("链表长度为:%d\n", get_count_node(h)); h = reverse_list(h); // 逆置单链表 print_list(h); // 遍历遍历 printf("链表长度为:%d\n", get_count_node(h)); ElemType d; if (GetElem(h, 2, &d)) { // 得到第二个元素的值 printf("第二个元素的值为:%d\n", d); } h = sort_list_with_no_head(h); // 对单链表进行排序 print_list(h); // 遍历遍历 printf("链表长度为:%d\n", get_count_node(h)); h = insert_node_order(h, 99); //有序插入99 print_list(h); // 遍历遍历 printf("链表长度为:%d\n", get_count_node(h)); if (LocateElem1(h, 33)) { // 按值查找,返回地址 printf("%d的地址: %p\n", 33, LocateElem1(h, 33)); } if (LocateElem2(h, 33)) { // 按值查找,返回位置序号 printf("%d的序号: %d\n", 33, LocateElem2(h, 33)); } insert_node(h, 2, 111); // 插入——在第2个结点前插入一个新结点 print_list(h); // 遍历遍历 printf("链表长度为:%d\n", get_count_node(h)); while (!ListEmpty(h)) { h = delete_a_node(h, 1, &d); printf("第1个结点: %d被删除\n", d); print_list(h); printf("链表长度为:%d\n", get_count_node(h)); } h = destroy_list(h); // 销毁链表 return 0; }
带头结点单链表
LinkedListWithHead.h
#ifndef __LINKEDLISTWITHHEAD_H__ #define __LINKEDLISTWITHHEAD_H__ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> typedef int ElemType; struct node { ElemType data; //数据域 保存数据 struct node *next; //指针域 保存逻辑上的下一个(关系) }; // 头结点的数据类型 保存链表的属性 struct list { struct node *first; // 指向第一个数据结点 struct node *last; // 指向最后一个数据结点 int NodeNum; // 记录链表的长度 /* 其他属性 */ }; struct list* create_list(); // 创建一个新链表,返回链表的首地址 void insert_node_order(struct list *list, ElemType d); // 有序插入 struct list* create_sort_list(); // 创建一个有序新链表,返回链表的首地址 void print_list(struct list *list); // 遍历遍历 struct list* clear_list(struct list *list); // 清空链表 /* add_a_node:在链表h中值为x的结点前面,增加一个结点 该结点的值为a,然后返回链表的首地址。 假设没有值为x的结点,则在尾部增加。如果有多个值为x 的结点则增加在第一个值为x的结点前面。 */ struct list* add_a_node(struct list *list, ElemType x, ElemType a); struct list* delete_node(struct list *list, ElemType x); // 在h指向的链表中,删除值为x的结点 void update_node(struct list *list, ElemType x, ElemType a); // 把链表中值为x的结点的值改成a struct list* destroy_list(struct list *list); // 销毁带头结点的单链表 void sort_list_with_head(struct list *list); // 对带头结点的单链表进行排序 void reverse_list(struct list *list); // 逆置链表 bool GetElem(struct list *list, int pos, ElemType *val); // 得到第i个元素的值 bool ListEmpty(struct list *list); // 判断链表是否为空 struct node* LocateElem1(struct list *list, ElemType e); // 按值查找,返回地址 int LocateElem2(struct list *list, ElemType e); // 按值查找,返回位置序号 bool insert_node(struct list *list, int i, ElemType e); // 插入——在第i个结点前插入一个值为e的新结点 bool delete_a_node(struct list *list, int i, ElemType *e); // 删除第i个结点 #endif
LinkedListWithHead.c
#include "LinkedListWithHead.h" /* create_list:创建一个新链表,返回链表的首地址 */ struct list* create_list() { ElemType d; struct node *pnew = NULL; // 指向新创建的结点 // step0:创建一个头结点并初始化 struct list *list = malloc(sizeof(*list)); list->first = NULL; // 指向第一个数据结点 list->last = NULL; // 指向最后一个数据结点 list->NodeNum = 0; // 链表长度 while (1) { // step1:每保存一个数据,就要创建一个结点(结构体) scanf("%d", &d); if (d == 0) { break; } pnew = malloc(sizeof(*pnew)); list->NodeNum++; // 每创建一个新数据结点,属性NodeNum就加一 // step2:把数据写入到结点中去 pnew->data = d; pnew->next = NULL; // step3:把结点加入到链表中 if (list->first == NULL) { // 从无到有,首尾结点都是pnew list->first = pnew; list->last = pnew; } else { // 从少到多 // 尾插 #if 1 list->last->next = pnew; // list->last 指向新结点 list->last = pnew; // list->last被pnew替代 #endif #if 0 // 头插 pnew->next = list->first; // 新结点指向list->first list->first = pnew; // list->first被pnew替代 #endif } } return list; } // 有序插入 void insert_node_order(struct list *list, ElemType d) { if (list == NULL) { return ; } // 创建一个新节点 struct node *pnew = (struct node*)malloc(sizeof(*pnew)); pnew->data = d; pnew->next = NULL; // 插入 /* 比第一个节点要小,头插法 比最后一个结点要大 尾插法 中间插,找第一个比它大的结点 */ if (list->first == NULL) { //从无到有 list->first = list->last = pnew; } else { struct node *p = list->first; // 遍历指针 struct node *pre = NULL; // 指向遍历指针的前驱结点 while (p) { // 找第一个比pnew大的结点 if (p->data > pnew->data) { break; } pre = p; p = p->next; } if (p == NULL) { // 没有找到比它大 尾插 list->last->next = pnew; list->last = pnew; } else { // 找到了 if (p == list->first) { // 找到的结点为第一个结点 // 头插 pnew->next = list->first; list->first = pnew; } else { // 中间插 pre->next = pnew; pnew->next = p; } } } list->NodeNum++; } /* create_sort_list:创建一个有序新链表,返回链表的首地址 */ struct list* create_sort_list() { ElemType d; struct node *pnew = NULL; // 指向新创建的结点 // step0:创建一个头结点并初始化 struct list *list = malloc(sizeof(*list)); list->first = NULL; // 指向第一个数据结点 list->last = NULL; // 指向最后一个数据结点 list->NodeNum = 0; // 链表长度 while (1) { // step1:每保存一个数据,就要创建一个结点(结构体) scanf("%d", &d); if (d == 0) { break; } pnew = malloc(sizeof(*pnew)); list->NodeNum++; // 每加入一个新结点,链表长度属性+1 // step2:把数据写入到结点中去 pnew->data = d; pnew->next = NULL; // step3:把结点加入到链表中 if (list->first == NULL) { // 从无到有 list->first = pnew; list->last = pnew; } else { // 从少到多 struct node *p = list->first; // 指向链表的第一个数据结点,作用找到第一个比新结点大的那个结点 struct node *pre = NULL; // 指向p指向的结点的前一个结点 while (p) { // <==> p != NULL 遍历链表 if (p->data > pnew->data) { // 找位置 break; } else { // 本结点不是,往后走 pre = p; p = p->next; } } if (p != NULL) { // 找到了一个比pnew大的结点 if (p == list->first) { // 头插 pnew->next = list->first; list->first = pnew; } else { // 中间插 pre->next = pnew; pnew->next = p; } } else { // 没找到 尾插 pre->next = pnew; list->last = pnew; // 更新头结点的last属性 } } } return list; } // 遍历遍历 void print_list(struct list *list) { if (list == NULL || list->NodeNum == 0) { return ; } struct node *p = list->first; // 遍历指针 while (p) { printf("%d ", p->data); p = p->next; } putchar('\n'); } // 清空链表 struct list* clear_list(struct list *list) { if (list == NULL || list->NodeNum == 0) { return list; } struct node *p = list->first; // 遍历指针 struct node *pc = NULL; // 指向被拆结点 while (p) { // 头删 pc = p; p = p->next; pc->next = NULL; free(pc); } list->first = NULL; list->last = NULL; list->NodeNum = 0; return list; } /* add_a_node:在链表h中值为x的结点前面,增加一个结点 该结点的值为a,然后返回链表的首地址。 假设没有值为x的结点,则在尾部增加。如果有多个值为x 的结点则增加在第一个值为x的结点前面。 */ struct list* add_a_node(struct list *list, ElemType x, ElemType a) { // 特殊情况 if (list == NULL) { return NULL; } // step1:创建一个值为a的新结点 struct node *pnew = malloc(sizeof(*pnew)); pnew->data = a; pnew->next = NULL; if (list->first == NULL) { // 从无到有 list->first = list->last = pnew; } else { struct node *p = list->first; // 遍历指针 struct node *pre = NULL; // 指向p指向的结点的前一个结点 // step2:找到值为x的结点 while (p) { // while (p != NULL) if (p->data == x) { // 找到了 break; } // 没找到,往后走 pre = p; p = p->next; } // step3:把新结点加入链表中 if (p != NULL) { // 找到了 if (p == list->first) { // 头插 pnew->next = list->first; // 新结点指向原链表的第一个数据结点 list->first = pnew; // 更新头结点的first属性 } else { // 中间插 // pnew->next = p; // 新结点指向p指向的结点 // pre->next = pnew; // p指向的结点的前一个结点 指向 新结点 pre->next = pnew; pnew->next = p; } } else { // 没找到 pre->next = pnew; // 尾插 list->last = pnew; // 更新头结点的属性last } } list->NodeNum++; // 更新链表的长度 return list; } /* delete_node:在h指向的链表中,删除值为x的结点 */ struct list* delete_node(struct list *list, ElemType x) { // 特殊情况 if (list == NULL || list->first == NULL) { return NULL; } struct node *p = list->first; // 遍历指针 struct node *pre = NULL; // 指向p指向的结点的前一个结点 // step1:找到值为x的结点 while (p) { if (p->data == x) { // 找到了 list->NodeNum--; // step2:删除值为x的结点 if (p == list->first) { // 删除第一个数据结点 list->first = list->first->next; p->next = NULL; // 为了工程规范,释放前把结点内的指针指向NULL free(p); p = list->first; if (list->NodeNum == 0) { // 当删除到没有数据结点时 list->last = NULL; } } else if (p == list->last) { // 删除最后一个数据结点 list->last = pre; list->last->next = NULL; p->next = NULL; // 为了工程规范,释放前把结点内的指针指向NULL free(p); } else { // 删中间 pre->next = p->next; p->next = NULL; // 为了工程规范,释放前把结点内的指针指向NULL free(p); p = pre->next; // p往后走,pre不动 } } else { // 没找到 往后走 pre = p; p = p->next; } } return list; } /* update_node:把链表中值为x的结点的值改成a */ void update_node(struct list *list, ElemType x, ElemType a) { struct node *p = list->first; // 遍历指针 while (p) { if (p->data == x) { p->data = a; } p = p->next; } } // 销毁带头结点的单链表 struct list* destroy_list(struct list *list) { if (list == NULL) { return list; } struct node *p = list->first; // 遍历指针 struct node *pc = NULL; // 指向要拆的那个数据结点 // 拆并释放数据结点 while (p) { // 头删 pc = p; p = p->next; pc->next = NULL; // 为了工程规范,释放前把结点内的指针指向NULL free(pc); } list->first = NULL; list->last = NULL; free(list); // 释放头结点 list = NULL; return list; } // 对带头结点的单链表进行排序 void sort_list_with_head(struct list *list) { if (list == NULL || list->NodeNum == 0 || list->NodeNum == 1) { return ; } // 1.遍历,将原来链表中的每一个结点依次摘下来 struct node *head = list->first; // 遍历指针 struct node *pc = NULL; // 要摘下来的结点 list->first = NULL; list->last = NULL; // 2.将摘下来的结点 插入到新的链表中 while (head) { // 摘 pc = head; head = head->next; pc->next = NULL; // 加到链表 if (list->first == NULL) { // 从无到有 list->first = list->last = pc; } else { // 找第一个比插入结点大的结点p struct node *p = list->first; // 遍历指针 struct node *pre = NULL; // 指向p指向的结点的前一个结点 while (p) { if (p->data > pc->data) { break; } pre = p; p = p->next; } if (p == NULL) { // 没有找到 尾插 list->last->next = pc; list->last = pc; } else { // 找到了 if (p == list->first) { // 头插法 pc->next = list->first; list->first = pc; } else { // 中间插 pre->next = pc; pc->next = p; } } } } } /* 逆置单链表(不能进行额外的申请结点) 1.(直接交换数据域) 2.(把原链表的每一个结点 摘下来,然后按照 头插法 插入到新的链表) */ void reverse_list(struct list *list) { if (list == NULL || list->NodeNum == 0 || list->NodeNum == 1) { return ; } struct node *head = list->first; // 遍历指针 struct node *pc = NULL; // 指向被拆结点 list->first = NULL; list->last = NULL; while (head) { // 1.把原链表的每一个结点摘下来 pc = head; head = head->next; pc->next = NULL; // 2.把摘下来的结点 按照头插法 插入 if (list->first == NULL) { // 从无到有 list->first = list->last = pc; } else { // 头插 pc->next = list->first; list->first = pc; } } } // 得到第i个元素的值 bool GetElem(struct list *list, int pos, ElemType *val) { // 特殊情况 if (list == NULL || list->NodeNum == 0 || pos < 1 || pos > list->NodeNum) { return false; } struct node *p = list->first; // 遍历指针 int i = 1; while (p) { if (i == pos) { *val = p->data; return true; } i++; p = p->next; } return false; } // 判断链表是否为空 bool ListEmpty(struct list *list) { if (list == NULL || list->NodeNum == 0) { return true; } return false; } /* 按值查找,返回地址 在链表L中查找值为e的数据元素 找到,则返回L中值为e的数据元素的地址,查找失败返回NULL */ struct node* LocateElem1(struct list *list, ElemType e) { if (list == NULL) { return NULL; } struct node *p = list->first; // 遍历指针 while (p && p->data != e) { p = p->next; } return p; } /* 按值查找,返回位置序号 在链表L中查找第一个值为e的数据元素 找到,则返回L中值为e的位置序号,查找失败返回0 */ int LocateElem2(struct list *list, ElemType e) { if (list == NULL) { return 0; } struct node *p = list->first; // 遍历指针 int j = 1; while (p && p->data != e) { p = p->next; j++; } if (p) { return j; } return 0; } // 插入——在第i个结点前插入一个值为e的新结点 bool insert_node(struct list *list, int i, ElemType e) { // 特殊情况 if (list == NULL || list->NodeNum == 0 || i < 1 || i > list->NodeNum) { return false; } struct node *pnew = malloc(sizeof(*pnew)); // 创建一个新结点 pnew->data = e; pnew->next = NULL; struct node *p = list->first; // 遍历指针 struct node *pre = NULL; // 遍历指针的前驱结点 int j = 1; while (j != i) { pre = p; p = p->next; j++; } if (p == list->first) { // 头插 pnew->next = list->first; list->first = pnew; } else { // 中间插 pre->next = pnew; pnew->next = p; } list->NodeNum++; // 链表长度+1 return true; } // 删除第i个结点 bool delete_a_node(struct list *list, int i, ElemType *e) { // 特殊情况 if (list == NULL || list->NodeNum == 0 || i < 1 || i > list->NodeNum) { return false; } struct node *p = list->first; // 遍历指针 struct node *pre = NULL; // 遍历指针的前驱结点 int j = 1; while (j != i) { pre = p; p = p->next; j++; } list->NodeNum--; // 链表长度减一 if (p == list->first) { // 头删 *e = p->data; // 保存被删结点数据 list->first = list->first->next; p->next = NULL; free(p); if (list->NodeNum == 0) { // 当删除到没有数据结点时 list->last = NULL; } } else if (p == list->last) { // 尾删 list->last = pre; list->last->next = NULL; *e = p->data; // 保存被删结点数据 free(p); } else { // 中间删 *e = p->data; pre->next = p->next; p->next = NULL; free(p); } return true; }
main.c
#include "LinkedListWithHead.h" int main(int argc, char *argv[]) { // struct list *list = create_list(); // 创建一个新链表,返回链表的首地址 struct list *list = create_sort_list(); // 创建一个有序新链表,返回链表的首地址 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); list = add_a_node(list, 3, 999); // 在值为3的结点前面增加一个值为999的结点 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); list = delete_node(list, 999); // 删除值为999的结点 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); update_node(list, 3, 33); // 把链表中值为3的结点的值改成33 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); reverse_list(list); // 逆置链表 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); ElemType d; if (GetElem(list, 2, &d)) { // 得到第二个元素的值 printf("第二个元素的值为:%d\n", d); } sort_list_with_head(list); //对链表进行排序 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); insert_node_order(list, 99); //有序插入99 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); if (LocateElem1(list, 33)) { // 按值查找,返回地址 printf("%d的地址: %p\n", 33, LocateElem1(list, 33)); } if (LocateElem2(list, 33)) { // 按值查找,返回位置序号 printf("%d的序号: %d\n", 33, LocateElem2(list, 33)); } if (insert_node(list, list->NodeNum, 111)) { // 插入——在第2个结点前插入一个新结点 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); } while (!ListEmpty(list)) { if (delete_a_node(list, 1, &d)) { printf("第1个结点: %d被删除\n", d); print_list(list); printf("链表长度为:%d\n", list->NodeNum); } } list = destroy_list(list); // 销毁链表 return 0; }
带头结点双链表
BothWithLinkedListWithHead.h
#ifndef __BOTHWITHLINKEDLISTWITHHEAD_H__ #define __BOTHWITHLINKEDLISTWITHHEAD_H__ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> typedef int ElemType; // 数据结点 struct node { ElemType data; // 数据域 存储数据 struct node *next; // 指针域 保存逻辑上的下一个(关系) struct node *prev; // 指针域 保存逻辑上的上一个(关系) }; // 头结点的数据类型 保存链表的属性 struct list { struct node *first; // 指向第一个数据结点 struct node *last; // 指向最后一个数据结点 int NodeNum; // 记录链表的长度 /* 其他属性 */ }; extern struct list* create_list(); extern void insert_node_order(struct list *list, ElemType d); extern struct list* create_sort_list(); extern void print_list(struct list *list); extern struct list* clear_list(struct list *list); extern struct list* clear_list(struct list *list); extern struct list* add_a_node(struct list *list, ElemType x, ElemType a); extern struct list* delete_node(struct list *list, ElemType x); extern void update_node(struct list *list, ElemType x, ElemType a); extern struct list* destroy_list(struct list *list); extern void sort_list_with_head(struct list *list); extern void reverse_list(struct list *list); extern bool GetElem(struct list *list, int pos, ElemType *val); extern bool ListEmpty(struct list *list); extern struct node* LocateElem1(struct list *list, ElemType e); extern int LocateElem2(struct list *list, ElemType e); extern bool insert_node(struct list *list, int i, ElemType e); extern bool delete_a_node(struct list *list, int i, ElemType *e); #endif
BothWithLinkedListWithHead.c
#include "BothWithLinkedListWithHead.h" /* create_list:创建一个新链表,返回链表的首地址 */ struct list* create_list() { ElemType d; struct node *pnew = NULL; // 指向新创建的结点 // step0:创建一个头结点并初始化 struct list *list = malloc(sizeof(*list)); list->first = NULL; // 指向第一个数据结点 list->last = NULL; // 指向最后一个数据结点 list->NodeNum = 0; // 链表长度 while (1) { // step1:每保存一个数据,就要创建一个结点(结构体) scanf("%d", &d); if (d == 0) { break; } pnew = malloc(sizeof(*pnew)); list->NodeNum++; // 每创建一个新数据结点,属性NodeNum就加一 // step2:把数据写入到结点中去 pnew->data = d; pnew->next = NULL; pnew->prev = NULL; // step3:把结点加入到链表中 if (list->first == NULL) { // 从无到有,首尾结点都是pnew list->first = pnew; list->last = pnew; } else { // 从少到多 // 尾插 #if 1 list->last->next = pnew; // list->last 指向新结点 pnew->prev = list->last; list->last = pnew; // list->last被pnew替代 #endif #if 0 // 头插 pnew->next = list->first; // 新结点指向list->first list->first->prev = pnew; list->first = pnew; // list->first被pnew替代 #endif } } return list; } // 有序插入 void insert_node_order(struct list *list, ElemType d) { if (list == NULL) { return ; } // 创建一个新节点 struct node *pnew = (struct node*)malloc(sizeof(*pnew)); pnew->data = d; pnew->next = NULL; pnew->prev = NULL; // 插入 /* 比第一个节点要小,头插法 比最后一个结点要大 尾插法 中间插,找第一个比它大的结点 */ if (list->first == NULL) { // 从无到有 list->first = list->last = pnew; } else { struct node *p = list->first; // 遍历指针 while (p) { // 找第一个比pnew大的结点 if (p->data > pnew->data) { break; } p = p->next; } if (p == NULL) { // 没有找到比它大 尾插 list->last->next = pnew; pnew->prev = list->last; list->last = pnew; } else { if (p == list->first) { // 找到的结点为第一个结点 // 头插 pnew->next = list->first; list->first->prev = pnew; list->first = pnew; } else { // 中间插 pnew->next = p; pnew->prev = p->prev; p->prev->next = pnew; p->prev = pnew; } } } list->NodeNum++; } /* create_sort_list:创建一个有序新链表,返回链表的首地址 */ struct list* create_sort_list() { ElemType d; struct node *pnew = NULL; // 指向新创建的结点 // step0:创建一个头结点并初始化 struct list *list = malloc(sizeof(*list)); list->first = NULL; // 指向第一个数据结点 list->last = NULL; // 指向最后一个数据结点 list->NodeNum = 0; // 链表长度 while (1) { // step1:每保存一个数据,就要创建一个结点(结构体) scanf("%d", &d); if (d == 0) { break; } pnew = malloc(sizeof(*pnew)); list->NodeNum++; // step2:把数据写入到结点中去 pnew->data = d; pnew->next = NULL; pnew->prev = NULL; // step3:把结点加入到链表中 if (list->first == NULL) { // 数据结点从无到有 list->first = pnew; list->last = pnew; } else { // 从少到多 struct node *p = list->first; // 指向链表的第一个数据结点,找第一个比新结点大的那个结点 while (p) { // <==> p != NULL 遍历链表 if (p->data > pnew->data) { // 找位置 break; } else { //本结点不是,往后走 p = p->next; } } if (p != NULL) { // 找到有第一个比pnew大的结点 if (p == list->first) { // 头插 pnew->next = list->first; list->first->prev = pnew; list->first = pnew; } else { // 中间插 pnew->next = p; pnew->prev = p->prev; p->prev->next = pnew; p->prev = pnew; } } else { // 没找到 尾插 list->last->next = pnew; pnew->prev = list->last; list->last = pnew; // 更新头结点的last属性 } } } return list; } // 遍历遍历 void print_list(struct list *list) { // 异常处理 if (list == NULL || list->NodeNum == 0) { return ; } struct node *p = list->first; // 遍历指针 while (p) { printf("%d ", p->data); p = p->next; } putchar('\n'); } // 清空链表 struct list* clear_list(struct list* list) { if (list == NULL || list->NodeNum == 0) { return list; } struct node *p = list->first; // 遍历指针 struct node *pc = NULL; // 指向被拆结点 while (p) { // 头删 pc = p; p = p->next; if (p) { p->prev = NULL; } pc->next = NULL; free(pc); } list->first = NULL; list->last = NULL; list->NodeNum = 0; return list; } /* add_a_node:在链表h中值为x的结点前面,增加一个结点 该结点的值为a,然后返回链表的首地址。 假设没有值为x的结点,则在尾部增加。如果有多个值为x 的结点则增加在第一个值为x的结点前面。 */ struct list* add_a_node(struct list* list, ElemType x, ElemType a) { // 异常处理 if (list == NULL) { return NULL; } // step1:创建一个值为a的新结点 struct node *pnew = malloc(sizeof(*pnew)); pnew->data = a; pnew->next = NULL; pnew->prev = NULL; if (list->first == NULL) { // 从无到有 list->first = list->last = pnew; } else { // step2:找到值为x的结点 struct node *p = list->first; // 遍历指针 while (p) { // while (p != NULL) if (p->data == x) { // 找到了 break; } p = p->next; // 没找到,往后走 } // step3:把新结点加入链表中 if (p != NULL) { // 找到了 if (p == list->first) { // 头插 pnew->next = list->first; // 新结点指向原链表的第一个数据结点 list->first->prev = pnew; list->first=pnew; // 更新头结点的first属性 } else { // 中间插 pnew->next = p; pnew->prev = p->prev; p->prev->next = pnew; p->prev = pnew; } } else { // 没找到 尾插 list->last->next = pnew; pnew->prev = list->last; list->last = pnew; // 更新头结点的属性last } } list->NodeNum++; // 更新链表的长度 return list; } /* delete_node:在h指向的链表中,删除值为x的结点 */ struct list* delete_node(struct list *list, ElemType x) { // 异常处理 if (list == NULL || list->first == NULL) { return NULL; } struct node* p = list->first; // 遍历指针 // step1:找到值为x的结点 while (p) { if (p->data == x) { // 找到了 list->NodeNum--; // 链表长度减一 // step2:删除值为x的结点 if (p == list->first) { // 删除第一个数据结点 list->first = list->first->next; if (list->first) { list->first->prev = NULL; } else { list->last = NULL; } p->next = NULL; // 为了工程规范,释放前把结点内的指针指向NULL free(p); p = list->first; // p往后走 } else if (p == list->last) { // 删除最后一个数据结点 list->last = p->prev; list->last->next = NULL; p->prev = NULL; free(p); } else { // 删中间 struct node *psave = p->next; // 用psave保存p的下一个结点 save:保存 p->prev->next = p->next; p->next->prev = p->prev; p->prev = NULL; p->next = NULL; free(p); p = psave; // p往后走 } } else { // 没找到 往后走 p = p->next; } } return list; } /* update_node:把h指向的链表中,值为x的结点的值改成a */ void update_node(struct list *list, ElemType x, ElemType a) { struct node *p = list->first; // p是遍历指针 while (p) { if (p->data == x) { p->data = a; } p = p->next; } } /* destroy_list:销毁带头双链表 */ struct list* destroy_list(struct list *list) { // 异常处理 if (list == NULL) { return NULL; } struct node *pc = list->first; // 指向被删结点 while (pc) // 头删 { list->first = list->first->next; if (list->first) { list->first->prev = NULL; } pc->next = NULL; free(pc); pc = list->first; } // 删除头结点 list->last = NULL; free(list); list == NULL; return list; } // 对带头结点的双链表进行排序 void sort_list_with_head(struct list *list) { // 异常处理 if (list == NULL || list->NodeNum == 0 || list->NodeNum == 1) { return ; } // 1.遍历,将原来链表中的每一个结点依次摘下来 struct node *head = list->first; // 指向数据结点的第一个节点、遍历指针 struct node *pc = NULL; // 要摘下来的结点 list->first = NULL; list->last = NULL; // 2.将摘下来的结点 插入到新的链表中 while (head) { // 头摘 pc = head; head = head->next; pc->next = NULL; pc->prev = NULL; // 加到链表 if (list->first == NULL) { // 从无到有 list->first = list->last = pc; } else { // 找第一个比插入结点大的结点p struct node *p = list->first; // 遍历指针 while (p) { if(p->data > pc->data) { break; } p = p->next; } if (p == NULL) { // 没有找到 尾插 list->last->next = pc; pc->prev = list->last; list->last = pc; } else { if (p == list->first) { // 头插法 pc->next = list->first; list->first->prev = pc; list->first = pc; } else { // 中间插 struct node *pre = p->prev; pc->next = p; pc->prev = pre; pre->next = pc; p->prev = pc; } } } } } /* 逆置双链表(不能进行额外的申请结点) 1.(直接交换数据域) 2.(把原链表的每一个结点 摘下来,然后按照 头插法 插入到新的链表) */ void reverse_list(struct list *list) { if (list == NULL || list->NodeNum == 0 || list->NodeNum == 1) { return ; } struct node *head = list->first; // 遍历指针 struct node *pc = head; // 指向被拆结点 list->first = NULL; list->last = NULL; while (head) { // 1.把原链表的每一个结点摘下来 pc = head; head = head->next; if (head) { head->prev = NULL; } pc->next = NULL; // 2.把摘下来的结点 按照头插法 插入 if (list->first == NULL) { // 从无到有 list->first = list->last = pc; } else { pc->next = list->first; list->first->prev = pc; list->first = pc; } } } // 得到第i个元素的值 bool GetElem(struct list *list, int pos, ElemType *val) { if (list == NULL || list->NodeNum == 0 || pos < 1 || pos > list->NodeNum) { return false; } struct node *p = list->first; // 遍历指针 int i = 1; while (p) { if (i == pos) { *val = p->data; return true; } i++; p = p->next; } return false; } // 判断链表是否为空 bool ListEmpty(struct list *list) { if (list == NULL || list->NodeNum == 0) { return true; } return false; } /* 按值查找,返回地址 在链表L中查找值为e的数据元素 找到,则返回L中值为e的数据元素的地址,查找失败返回NULL */ struct node* LocateElem1(struct list *list, ElemType e) { if (list == NULL) { return NULL; } struct node *p = list->first; while (p && p->data != e) { p = p->next; } return p; } /* 按值查找,返回位置序号 在链表L中查找第一个值为e的数据元素 找到,则返回L中值为e的位置序号,查找失败返回0 */ int LocateElem2(struct list *list, ElemType e) { if (list == NULL) { return 0; } struct node *p = list->first; // 遍历指针 int j = 1; while (p && p->data != e) { p = p->next; j++; } if (p) { return j; } return 0; } // 插入——在第i个结点前插入一个值为e的新结点 bool insert_node(struct list *list, int i, ElemType e) { // 异常处理 if (list == NULL || list->NodeNum == 0 || i < 1 || i > list->NodeNum) { return false; } struct node *pnew = malloc(sizeof(*pnew)); // 创建一个新结点 pnew->data = e; pnew->next = NULL; pnew->prev = NULL; struct node *p = list->first; // 遍历指针 int j = 1; while (j != i) { p = p->next; j++; } if (j == 1) { // 头插 pnew->next = list->first; list->first->prev = pnew; list->first = pnew; } else { // 中间插 pnew->next = p; pnew->prev = p->prev; p->prev->next = pnew; p->prev = pnew; } list->NodeNum++; // 链表长度加1 return true; } // 删除第i个结点 bool delete_a_node(struct list *list, int i, ElemType *e) { // 特殊情况 if (list == NULL || list->NodeNum == 0 || i < 1 || i > list->NodeNum) { return false; } struct node *p = list->first; // 遍历指针 int j = 1; while (j != i) { p = p->next; j++; } list->NodeNum--; // 链表长度减一 if (j == 1) { // 头删 list->first = list->first->next; if (list->first) { list->first->prev = NULL; } else { // 链表长度 == 0 list->last = NULL; } *e = p->data; // 保存被拆结点数据 p->next = NULL; free(p); } else if (p == list->last) { // 尾删 list->last = p->prev; list->last->next = NULL; *e = p->data; // 保存被拆结点数据 p->prev = NULL; free(p); } else { // 中间删 struct node *pre = p->prev; // 被删结点的前驱结点 *e = p->data; // 保存被拆结点数据 pre->next = p->next; p->next->prev = pre; p->next = NULL; p->prev = NULL; free(p); } return true; }
main.c
#include "BothWithLinkedListWithHead.h" int main(int argc, char *argv[]) { // struct list *list = create_list(); // 创建一个新链表,返回链表的首地址 struct list *list = create_sort_list(); // 创建一个有序新链表,返回链表的首地址 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); list = add_a_node(list, 3, 999); // 在值为3的结点前面增加一个值为999的结点 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); list = delete_node(list, 999); // 删除值为999的结点 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); update_node(list, 3, 33); // 把链表中值为3的结点的值改成33 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); reverse_list(list); // 逆置链表 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); ElemType d; if (GetElem(list, 2, &d)) { // 得到第二个元素的值 printf("第二个元素的值为:%d\n", d); } sort_list_with_head(list); //对链表进行排序 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); insert_node_order(list, 99); //有序插入99 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); if (LocateElem1(list, 33)) { // 按值查找,返回地址 printf("%d的地址: %p\n", 33, LocateElem1(list, 33)); } if (LocateElem2(list, 33)) { // 按值查找,返回位置序号 printf("%d的序号: %d\n", 33, LocateElem2(list, 33)); } if (insert_node(list, list->NodeNum, 111)) { // 插入——在第2个结点前插入一个新结点 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); } while (!ListEmpty(list)) { if (delete_a_node(list, 1, &d)) { printf("第1个结点: %d被删除\n", d); print_list(list); printf("链表长度为:%d\n", list->NodeNum); } } list = destroy_list(list); // 销毁链表 return 0; }
带头循环单链表
CircleLinkedListWithHead.h
#ifndef __CIRCLELINKEDLISTWITHHEAD_H__ #define __CIRCLELINKEDLISTWITHHEAD_H__ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> typedef int ElemType; // 数据结点 struct node { ElemType data; // 数据域 struct node *next; // 指针域 }; // 头结点的数据类型 保存链表的属性 struct list { struct node *first; // 指向第一个数据结点 struct node *last; // 指向最后一个数据结点 int NodeNum; // 记录链表的长度 /* 其他属性 */ }; extern struct list* create_list(); extern void insert_node_order(struct list *list, ElemType d); extern struct list* create_sort_list(); extern void print_list(struct list *list); extern struct list* clear_list(struct list *list); extern struct list* add_a_node(struct list *list, ElemType x, ElemType a); extern struct list* delete_node(struct list *list, ElemType x); extern void update_node(struct list *list, ElemType x, ElemType a); extern struct list* destroy_list(struct list *list); extern void sort_list(struct list *list); extern void reverse_list(struct list *list); extern bool GetElem(struct list *list, int pos, ElemType *val); extern bool ListEmpty(struct list *list); extern struct node* LocateElem1(struct list *list, ElemType e); extern int LocateElem2(struct list *list, ElemType e); extern bool insert_node(struct list *list, int i, ElemType e); extern bool delete_a_node(struct list *list, int i, ElemType *e); #endif
CircleLinkedListWithHead.c
#include "CircleLinkedListWithHead.h" /* create_list:创建一个新链表,返回链表的首地址 */ struct list* create_list() { ElemType d; struct node *pnew = NULL; // 指向新创建的结点 // step0:创建一个头结点并初始化 struct list *list = malloc(sizeof(*list)); list->first = NULL; // 指向第一个数据结点 list->last = NULL; // 指向最后一个数据结点 list->NodeNum = 0; // 链表长度 while (1) { // step1:每保存一个数据,就要创建一个结点(结构体) scanf("%d", &d); if (d == 0) { break; } pnew = malloc(sizeof(*pnew)); list->NodeNum++; // 每创建一个新数据结点,属性NodeNum就加一 // step2:把数据写入到结点中去 pnew->data = d; pnew->next = NULL; // step3:把结点加入到链表中 if (list->first == NULL) { // 从无到有,首尾结点都是pnew list->first = pnew; list->last = pnew; } else { // 从少到多 // 尾插 #if 1 list->last->next = pnew; // list->last 指向新结点 list->last = pnew; // list->last被pnew替代 #endif #if 0 // 头插 pnew->next = list->first; // 新结点指向list->first list->first = pnew; // list->first被pnew替代 #endif } } if (list->NodeNum != 0) { list->last->next = list->first; } return list; } // 有序插入 void insert_node_order(struct list *list, ElemType d) { if (list == NULL) { return ; } // 创建一个新节点 struct node *pnew = (struct node*)malloc(sizeof(*pnew)); pnew->data = d; pnew->next = NULL; // 插入 /* 比第一个节点要小,头插法 比最后一个结点要大 尾插法 中间插,找第一个比它大的结点 */ if (list->first == NULL) { // 从无到有 list->first = list->last = pnew; } else { struct node *p = list->first; // 遍历指针 struct node *pre = NULL; // 指向遍历指针的前驱结点 int len = list->NodeNum; // 链表长度 while (len--) { // 找第一个比pnew大的结点 if (p->data > pnew->data) { break; } pre = p; p = p->next; } if (len == -1) { // 没有找到比它大 尾插 list->last->next = pnew; list->last = pnew; } else { // 找到了 if (p == list->first) { // 找到的结点为第一个结点 // 头插 pnew->next = list->first; list->first = pnew; } else { // 中间插 pre->next = pnew; pnew->next = p; } } } list->NodeNum++; printf("%d\n", list->NodeNum); list->last->next = list->first; } /* create_sort_list:创建一个有序新链表,返回链表的首地址 */ struct list* create_sort_list() { ElemType d; struct node *pnew = NULL; // 指向新创建的结点 // step0:创建一个头结点并初始化 struct list *list = malloc(sizeof(*list)); list->first = NULL; // 指向第一个数据结点 list->last = NULL; // 指向最后一个数据结点 list->NodeNum = 0; // 链表长度 while (1) { // step1:每保存一个数据,就要创建一个结点(结构体) scanf("%d", &d); if (d == 0) { break; } pnew = malloc(sizeof(*pnew)); list->NodeNum++; // 每加入一个新结点,链表长度属性+1 // step2:把数据写入到结点中去 pnew->data = d; pnew->next = NULL; // step3:把结点加入到链表中 if (list->first == NULL) { // 从无到有 list->first = pnew; list->last = pnew; } else { // 从少到多 struct node *p = list->first; // 指向链表的第一个数据结点,作用找到第一个比新结点大的那个结点 struct node *pre = NULL; // 指向p指向的结点的前一个结点 while (p) { // <==> p != NULL 遍历链表 if (p->data > pnew->data) { // 找位置 break; } else { // 本结点不是,往后走 pre = p; p = p->next; } } if (p != NULL) { // 找到了一个比pnew大的结点 if (p == list->first) { // 头插 pnew->next = list->first; list->first = pnew; } else { // 中间插 pre->next = pnew; pnew->next = p; } } else { // 没找到 尾插 pre->next = pnew; list->last = pnew; // 更新头结点的last属性 } } } if (list->NodeNum != 0) { list->last->next = list->first; } return list; } // 遍历遍历 void print_list(struct list *list) { if (list == NULL || list->NodeNum == 0) { return ; } struct node *p = list->first; // 遍历指针 int len = list->NodeNum * 2; while (len--) { printf("%d ", p->data); p = p->next; } putchar('\n'); } // 清空链表 struct list* clear_list(struct list *list) { if (list == NULL || list->NodeNum == 0) { return list; } // 变为普通单链表 list->last->next = NULL; struct node *p = list->first; // 遍历指针 struct node *pc = NULL; // 指向被拆结点 while (p) { // 头删 pc = p; p = p->next; pc->next = NULL; free(pc); } list->first = NULL; list->last = NULL; list->NodeNum = 0; return list; } /* add_a_node:在链表h中值为x的结点前面,增加一个结点 该结点的值为a,然后返回链表的首地址。 假设没有值为x的结点,则在尾部增加。如果有多个值为x 的结点则增加在第一个值为x的结点前面。 */ struct list* add_a_node(struct list *list, ElemType x, ElemType a) { // 特殊情况 if (list == NULL) { return NULL; } // step1:创建一个值为a的新结点 struct node *pnew = malloc(sizeof(*pnew)); pnew->data = a; pnew->next = NULL; if (list->first == NULL) { // 从无到有 list->first = list->last = pnew; } else { struct node *p = list->first; // 遍历指针 struct node *pre = NULL; // 指向p指向的结点的前一个结点 // step2:找到值为x的结点 int len = list->NodeNum; while (len--) { if (p->data == x) { // 找到了 break; } // 没找到,往后走 pre = p; p = p->next; } // step3:把新结点加入链表中 if (len != -1) { // 找到了 if (p == list->first) { // 头插 pnew->next = list->first; // 新结点指向原链表的第一个数据结点 list->first = pnew; // 更新头结点的first属性 } else { // 中间插 // pnew->next = p; // 新结点指向p指向的结点 // pre->next = pnew; // p指向的结点的前一个结点 指向 新结点 pre->next = pnew; pnew->next = p; } } else { // 没找到 pre->next = pnew; // 尾插 list->last = pnew; // 更新头结点的属性last } } list->NodeNum++; // 更新链表的长度 list->last->next = list->first; return list; } /* delete_node:在h指向的链表中,删除值为x的结点 */ struct list* delete_node(struct list* list, ElemType x) { // 特殊情况 if (list == NULL || list->first == NULL) { return NULL; } struct node *p = list->first; // 遍历指针 struct node *pre = NULL; // 指向p指向的结点的前一个结点 // step1:找到值为x的结点 int len = list->NodeNum; while (len--) { if (p->data == x) { // 找到了 list->NodeNum--; // step2:删除值为x的结点 if (p == list->first) { // 删除第一个数据结点 list->first = list->first->next; // 如果链表只有一个结点,list->first->next = list->first p->next = NULL; // 为了工程规范,释放前把结点内的指针指向NULL free(p); p = list->first; if (list->NodeNum == 0) { // 当删除到没有数据结点时 list->first = NULL; // 注意:这一步不能少 list->last = NULL; } } else if (p == list->last) { // 删除最后一个数据结点 list->last = pre; list->last->next = NULL; p->next = NULL; // 为了工程规范,释放前把结点内的指针指向NULL free(p); } else { // 删中间 pre->next = p->next; p->next = NULL; // 为了工程规范,释放前把结点内的指针指向NULL free(p); p = pre->next; // p往后走,pre不动 } } else { // 没找到 往后走 pre = p; p = p->next; } } if (list->NodeNum != 0) { list->last->next = list->first; } return list; } /* update_node:把list指向的链表中,值为x的结点的值改成a */ void update_node(struct list *list, ElemType x, ElemType a) { struct node *p = list->first; // 遍历指针 int len = list->NodeNum; while (len--) { if (p->data == x) { p->data = a; } p = p->next; } } /* destroy_list:销毁单向循环链表 */ struct list* destroy_list(struct list *list) { if (list == NULL) { return list; } if (list->last != NULL) { list->last->next = NULL; // 先把循环的属性去掉 struct node *p = list->first; // 遍历指针 struct node *pc = NULL; // 指向要拆的那个数据结点 // 拆并释放数据结点 while (p) { // 头删 pc = p; p = p->next; pc->next = NULL; // 为了工程规范,释放前把结点内的指针指向NULL free(pc); } list->first = NULL; list->last = NULL; } free(list); // 释放头结点 list = NULL; return list; } // 对带头结点的循环单链表进行排序 void sort_list(struct list *list) { if (list == NULL || list->NodeNum == 0 || list->NodeNum == 1) { return ; } list->last->next = NULL; // 变成普通带头结点单链表 // 1.遍历,将原来链表中的每一个结点依次摘下来 struct node *head = list->first; // 遍历指针 struct node *pc = NULL; // 要摘下来的结点 list->first = NULL; list->last = NULL; // 2.将摘下来的结点 插入到新的链表中 while (head) { // 摘 pc = head; head = head->next; pc->next = NULL; // 加到链表 if (list->first == NULL) { // 从无到有 list->first = list->last = pc; } else { // 找第一个比插入结点大的结点p struct node *p = list->first; // 遍历指针 struct node *pre = NULL; // 指向p指向的结点的前一个结点 while (p) { if (p->data > pc->data) { break; } pre = p; p = p->next; } if (p == NULL) { // 没有找到 尾插 list->last->next = pc; list->last = pc; } else { // 找到了 if (p == list->first) { // 头插法 pc->next = list->first; list->first = pc; } else { // 中间插 pre->next = pc; pc->next = p; } } } } list->last->next = list->first; // 变回带头结点循环单链表 } /* 逆置循环单链表(不能进行额外的申请结点) 1.(直接交换数据域) 2.(把原链表的每一个结点 摘下来,然后按照 头插法 插入到新的链表) */ void reverse_list(struct list *list) { if (list == NULL || list->NodeNum == 0 || list->NodeNum == 1) { return ; } list->last->next = NULL; // 变成普通带头结点单链表 struct node *head = list->first; // 遍历指针 struct node *pc = NULL; // 指向被拆结点 list->first = NULL; list->last = NULL; while (head) { // 1.把原链表的每一个结点摘下来 pc = head; head = head->next; pc->next = NULL; // 2.把摘下来的结点 按照头插法 插入 if (list->first == NULL) { // 从无到有 list->first = list->last = pc; } else { // 头插 pc->next = list->first; list->first = pc; } } list->last->next = list->first; // 变回带头结点循环单链表 } // 得到第i个元素的值 bool GetElem(struct list *list, int pos, ElemType *val) { // 特殊情况 if (list == NULL || list->NodeNum == 0 || pos < 1 || pos > list->NodeNum) { return false; } list->last->next = NULL; // 变成普通带头结点单链表 struct node *p = list->first; // 遍历指针 int i = 1; while (p) { if (i == pos) { *val = p->data; list->last->next = list->first; // 变回带头结点循环单链表 return true; } i++; p = p->next; } list->last->next = list->first; // 变回带头结点循环单链表 return false; } // 判断链表是否为空 bool ListEmpty(struct list *list) { if (list == NULL || list->NodeNum == 0) { return true; } return false; } /* 按值查找,返回地址 在链表L中查找值为e的数据元素 找到,则返回L中值为e的数据元素的地址,查找失败返回NULL */ struct node* LocateElem1(struct list *list, ElemType e) { if (list == NULL) { return NULL; } struct node *p = list->first; // 遍历指针 int len = list->NodeNum; while (len-- && p->data != e) { p = p->next; } return p; } /* 按值查找,返回位置序号 在链表L中查找第一个值为e的数据元素 找到,则返回L中值为e的位置序号,查找失败返回0 */ int LocateElem2(struct list *list, ElemType e) { if (list == NULL) { return 0; } struct node *p = list->first; // 遍历指针 int j = 1; int len = list->NodeNum; while (len-- && p->data != e) { p = p->next; j++; } if (p) { return j; } return 0; } // 插入——在第i个结点前插入一个值为e的新结点 bool insert_node(struct list *list, int i, ElemType e) { // 特殊情况 if (list == NULL || list->NodeNum == 0 || i < 1 || i > list->NodeNum) { return false; } // 变成普通带头结点单链表 list->last->next = NULL; struct node *pnew = malloc(sizeof(*pnew)); // 创建一个新结点 pnew->data = e; pnew->next = NULL; struct node *p = list->first; // 遍历指针 struct node *pre = NULL; // 遍历指针的前驱结点 int j = 1; while (j != i) { pre = p; p = p->next; j++; } if (p == list->first) { // 头插 pnew->next = list->first; list->first = pnew; } else { // 中间插 pre->next = pnew; pnew->next = p; } list->NodeNum++; // 链表长度+1 list->last->next = list->first; // 变回带头结点循环单链表 return true; } // 删除第i个结点 bool delete_a_node(struct list *list, int i, ElemType *e) { // 特殊情况 if (list == NULL || list->NodeNum == 0 || i < 1 || i > list->NodeNum) { return false; } // 变成普通带头结点单链表 list->last->next = NULL; struct node *p = list->first; // 遍历指针 struct node *pre = NULL; // 遍历指针的前驱结点 int j = 1; while (j != i) { pre = p; p = p->next; j++; } list->NodeNum--; // 链表长度减一 if (p == list->first) { // 头删 *e = p->data; // 保存被删结点数据 list->first = list->first->next; p->next = NULL; free(p); if (list->NodeNum == 0) { // 当删除到没有数据结点时 list->first = NULL; list->last = NULL; } } else if (p == list->last) { // 尾删 list->last = pre; list->last->next = NULL; *e = p->data; // 保存被删结点数据 free(p); } else { // 中间删 *e = p->data; pre->next = p->next; p->next = NULL; free(p); } // 变回带头结点循环单链表 if (list->NodeNum) { list->last->next = list->first; } return true; }
main.c
#include "CircleLinkedListWithHead.h" int main(int argc, char *argv[]) { // struct list *list = create_list(); // 创建一个新链表,返回链表的首地址 struct list *list = create_sort_list(); // 创建一个有序新链表,返回链表的首地址 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); list = add_a_node(list, 3, 999); print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); list = delete_node(list, 999); // 删除值为999的结点 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); update_node(list, 3, 33); // 把链表中值为3的结点的值改成33 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); reverse_list(list); // 逆置链表 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); ElemType d; if (GetElem(list, 2, &d)) { // 得到第二个元素的值 printf("第二个元素的值为:%d\n", d); } sort_list(list); // 对链表进行排序 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); insert_node_order(list, 99); // 有序插入99 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); if (LocateElem1(list, 33)) { // 按值查找,返回地址 printf("%d的地址: %p\n", 33, LocateElem1(list, 33)); } if (LocateElem2(list, 33)) { // 按值查找,返回位置序号 printf("%d的序号: %d\n", 33, LocateElem2(list, 33)); } if (insert_node(list, list->NodeNum, 111)) { // 插入——在第2个结点前插入一个新结点 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); } while (!ListEmpty(list)) { if (delete_a_node(list, 1, &d)) { printf("第1个结点: %d被删除\n", d); print_list(list); printf("链表长度为:%d\n", list->NodeNum); } } list = destroy_list(list); // 销毁链表 return 0; }
带头循环双链表
BothWithCircleLinkedListWithHead.h
#ifndef __BOTHWITHCIRCLELINKEDLISTWITHHEAD_H__ #define __BOTHWITHCIRCLELINKEDLISTWITHHEAD_H__ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> typedef int ElemType; // 数据结点 struct node { ElemType data; // 数据域 存储数据 struct node *next; // 指针域 保存逻辑上的下一个(关系) struct node *prev; // 指针域 保存逻辑上的上一个(关系) }; // 头结点的数据类型 保存链表的属性 struct list { struct node *first; // 指向第一个数据结点 struct node *last; // 指向最后一个数据结点 int NodeNum; // 记录链表的长度 /* 其他属性 */ }; extern struct list* create_list(); extern void insert_node_order(struct list *list, ElemType d); extern struct list* create_sort_list(); extern void print_list(struct list *list); extern struct list* clear_list(struct list *list); extern struct list* add_a_node(struct list *list, ElemType x, ElemType a); extern struct list* delete_node(struct list *list, ElemType x); extern void update_node(struct list *list, ElemType x, ElemType a); extern struct list* destroy_list(struct list *list); extern void sort_list_with_head(struct list *list); extern void reverse_list(struct list *list); extern bool GetElem(struct list *list, int pos, ElemType *val); extern bool ListEmpty(struct list *list); extern struct node* LocateElem1(struct list *list, ElemType e); extern int LocateElem2(struct list *list, ElemType e); extern bool insert_node(struct list *list, int i, ElemType e); extern bool delete_a_node(struct list *list, int i, ElemType *e); #endif
BothWithCircleLinkedListWithHead.c
#include "BothWithCircleLinkedListWithHead.h" /* create_list:创建一个循环双链表,返回链表的首地址 */ struct list* create_list() { ElemType d; struct node *pnew = NULL; // 指向新创建的结点 // step0:创建一个头结点并初始化 struct list *list = malloc(sizeof(*list)); list->first = NULL; // 指向第一个数据结点 list->last = NULL; // 指向最后一个数据结点 list->NodeNum = 0; // 链表长度 while (1) { // step1:每保存一个数据,就要创建一个结点(结构体) scanf("%d", &d); if (d == 0) { break; } pnew = malloc(sizeof(*pnew)); list->NodeNum++; // 每创建一个新数据结点,属性NodeNum就加一 // step2:把数据写入到结点中去 pnew->data = d; pnew->next = NULL; pnew->prev = NULL; // step3:把结点加入到链表中 if (list->first == NULL) { // 从无到有,首尾结点都是pnew list->first = pnew; list->last = pnew; } else { // 从少到多 // 尾插 #if 1 list->last->next = pnew; // list->last 指向新结点 pnew->prev = list->last; list->last = pnew; // list->last被pnew替代 #endif #if 0 // 头插 pnew->next = list->first; // 新结点指向list->first list->first->prev = pnew; list->first = pnew; // list->first被pnew替代 #endif } } if (list->NodeNum != 0) { list->last->next = list->first; list->first->prev = list->last; } return list; } // 有序插入 void insert_node_order(struct list *list, ElemType d) { if (list == NULL) { return ; } // 创建一个新节点 struct node *pnew = (struct node*)malloc(sizeof(*pnew)); pnew->data = d; pnew->next = NULL; pnew->prev = NULL; // 插入 /* 比第一个节点要小,头插法 比最后一个结点要大 尾插法 中间插,找第一个比它大的结点 */ if (list->first == NULL) { // 从无到有 list->first = list->last = pnew; } else { struct node *p = list->first; // 遍历指针 int len = list->NodeNum; //数据结点的个数 while (len--) { // 找第一个比pnew大的结点 if (p->data > pnew->data) { break; } p = p->next; } if (len == -1) { // <==> p == NULL 没有找到比它大 尾插 list->last->next = pnew; pnew->prev = list->last; list->last = pnew; } else { if (p == list->first) { // 找到的结点为第一个结点 // 头插 pnew->next = list->first; list->first->prev = pnew; list->first = pnew; } else { // 中间插 pnew->next = p; pnew->prev = p->prev; p->prev->next = pnew; p->prev = pnew; } } } list->NodeNum++; // 首尾相连 list->last->next = list->first; list->first->prev = list->last; } /* create_sort_list:创建一个新的有序循环双链表,返回链表的首地址 */ struct list* create_sort_list() { ElemType d; struct node *pnew = NULL; // 指向新创建的结点 // step0:创建一个头结点并初始化 struct list *list = malloc(sizeof(*list)); list->first = NULL; // 指向第一个数据结点 list->last = NULL; // 指向最后一个数据结点 list->NodeNum = 0; // 链表长度 while (1) { // step1:每保存一个数据,就要创建一个结点(结构体) scanf("%d", &d); if (d == 0) { break; } pnew = malloc(sizeof(*pnew)); list->NodeNum++; // step2:把数据写入到结点中去 pnew->data = d; pnew->next = NULL; pnew->prev = NULL; // step3:把结点加入到链表中 if (list->first == NULL) { // 数据结点从无到有 list->first = pnew; list->last = pnew; } else { // 从少到多 struct node *p = list->first; // 指向链表的第一个数据结点,找第一个比新结点大的那个结点 while (p) { // <==> p != NULL 遍历链表 if (p->data > pnew->data) { // 找位置 break; } else { //本结点不是,往后走 p = p->next; } } if (p != NULL) { // 找到有第一个比pnew大的结点 if (p == list->first) { // 头插 pnew->next = list->first; list->first->prev = pnew; list->first = pnew; } else { // 中间插 pnew->next = p; pnew->prev = p->prev; p->prev->next = pnew; p->prev = pnew; } } else { // 没找到 尾插 list->last->next = pnew; pnew->prev = list->last; list->last = pnew; // 更新头结点的last属性 } } } if (list->NodeNum != 0) { //链表不为空 首尾相连 list->last->next = list->first; list->first->prev = list->last; } return list; } // 遍历遍历 void print_list(struct list *list) { // 异常处理 if (list == NULL || list->NodeNum == 0) { return ; } struct node *p = list->first; // 遍历指针 int len = list->NodeNum * 2; while (len--) { printf("%d ", p->data); p = p->next; } putchar('\n'); } // 清空链表 struct list* clear_list(struct list *list) { if (list == NULL || list->NodeNum == 0) { return list; } // 变为普通双链表 list->first->prev = NULL; list->last->next = NULL; struct node *p = list->first; // 遍历指针 struct node *pc = NULL; // 指向被拆结点 while (p) { // 头删 pc = p; p = p->next; if (p) { p->prev = NULL; } pc->next = NULL; free(pc); } list->first = NULL; list->last = NULL; list->NodeNum = 0; return list; } /* add_a_node:在链表h中值为x的结点前面,增加一个结点 该结点的值为a,然后返回链表的首地址。 假设没有值为x的结点,则在尾部增加。如果有多个值为x 的结点则增加在第一个值为x的结点前面。 */ struct list* add_a_node(struct list *list, ElemType x, ElemType a) { // 异常处理 if (list == NULL) { return NULL; } // step1:创建一个值为a的新结点 struct node *pnew = malloc(sizeof(*pnew)); pnew->data = a; pnew->next = NULL; pnew->prev = NULL; if (list->first == NULL) { // 从无到有 list->first = list->last = pnew; } else { // step2:找到值为x的结点 struct node *p = list->first; // 遍历指针 while (p) { // while (p != NULL) if (p->data == x) { // 找到了 break; } p = p->next; // 没找到,往后走 } // step3:把新结点加入链表中 if (p != NULL) { // 找到了 if (p == list->first) { // 头插 pnew->next = list->first; // 新结点指向原链表的第一个数据结点 list->first->prev = pnew; list->first=pnew; // 更新头结点的first属性 } else { // 中间插 pnew->next = p; pnew->prev = p->prev; p->prev->next = pnew; p->prev = pnew; } } else { // 没找到 尾插 list->last->next = pnew; pnew->prev = list->last; list->last = pnew; // 更新头结点的属性last } } list->NodeNum++; // 更新链表的长度 // 变成循环双链表 list->last->next = list->first; list->first->prev =list->last; return list; } /* delete_node:在h指向的链表中,删除值为x的结点 */ struct list* delete_node(struct list *list, ElemType x) { // 异常处理 if (list == NULL || list->first == NULL) { return NULL; } // 改成普通双链表 list->first->prev = NULL; list->last->next = NULL; struct node* p = list->first; // 遍历指针 // step1:找到值为x的结点 while (p) { if (p->data == x) { // 找到了 list->NodeNum--; // 链表长度减一 // step2:删除值为x的结点 if (p == list->first) { // 删除第一个数据结点 list->first = list->first->next; if (list->first) { list->first->prev = NULL; } else { list->last = NULL; } p->next = NULL; // 为了工程规范,释放前把结点内的指针指向NULL free(p); p = list->first; // p往后走 } else if (p == list->last) { // 删除最后一个数据结点 list->last = p->prev; list->last->next = NULL; p->prev = NULL; free(p); } else { // 删中间 struct node *psave = p->next; // 用psave保存p的下一个结点 save:保存 p->prev->next = p->next; p->next->prev = p->prev; p->prev = NULL; p->next = NULL; free(p); p = psave; // p往后走 } } else { // 没找到 往后走 p = p->next; } } if (list->NodeNum != 0) { // 如果链表不为空,变回循环双链表 list->last->next = list->first; list->first->prev =list->last; } return list; } /* update_node:把h指向的链表中,值为x的结点的值改成a */ void update_node(struct list *list, ElemType x, ElemType a) { struct node *p = list->first; // p是遍历指针 int len = list->NodeNum; while (len--) { if (p->data == x) { p->data = a; } p = p->next; } } /* destroy_list:销毁双向循环链表 */ struct list* destroy_list(struct list *list) { // 异常处理 if (list == NULL) { return NULL; } if (list->first != NULL) { // 循环双链表不为空 // 变成普通双链表 list->first->prev = NULL; list->last->next = NULL; struct node *pc = list->first; // 指向被删结点 while (pc) // 头删 { list->first = list->first->next; if (list->first) { list->first->prev = NULL; } pc->next = NULL; free(pc); pc = list->first; } list->last = NULL; // 工程规范 list->NodeNum = 0; } // 删除头结点 free(list); list == NULL; return list; } // 对带头结点的循环双链表进行排序 void sort_list_with_head(struct list *list) { // 异常处理 if (list == NULL || list->NodeNum == 0 || list->NodeNum == 1) { return ; } // 变成普通双链表 list->first->prev = NULL; list->last->next = NULL; // 1.遍历,将原来链表中的每一个结点依次摘下来 struct node *head = list->first; // 指向数据结点的第一个节点、遍历指针 struct node *pc = NULL; // 要摘下来的结点 list->first = NULL; list->last = NULL; // 2.将摘下来的结点 插入到新的链表中 while (head) { // 头摘 pc = head; head = head->next; pc->next = NULL; pc->prev = NULL; // 加到链表 if (list->first == NULL) { // 从无到有 list->first = list->last = pc; } else { // 找第一个比插入结点大的结点p struct node *p = list->first; // 遍历指针 while (p) { if(p->data > pc->data) { break; } p = p->next; } if (p == NULL) { // 没有找到 尾插 list->last->next = pc; pc->prev = list->last; list->last = pc; } else { if (p == list->first) { // 头插法 pc->next = list->first; list->first->prev = pc; list->first = pc; } else { // 中间插 struct node *pre = p->prev; pc->next = p; pc->prev = pre; pre->next = pc; p->prev = pc; } } } } // 变回循环双链表 list->first->prev = list->last; list->last->next = list->first; } /* 逆置循环双链表(不能进行额外的申请结点) 1.(直接交换数据域) 2.(把原链表的每一个结点 摘下来,然后按照 头插法 插入到新的链表) */ void reverse_list(struct list *list) { if (list == NULL || list->NodeNum == 0 || list->NodeNum == 1) { return ; } // 变成普通双链表 list->first->prev = NULL; list->last->next = NULL; struct node *head = list->first; // 遍历指针 struct node *pc = head; // 指向被拆结点 list->first = NULL; list->last = NULL; while (head) { // 1.把原链表的每一个结点摘下来 pc = head; head = head->next; if (head) { head->prev = NULL; } pc->next = NULL; // 2.把摘下来的结点 按照头插法 插入 if (list->first == NULL) { // 从无到有 list->first = list->last = pc; } else { pc->next = list->first; list->first->prev = pc; list->first = pc; } } // 变回循环双链表 list->first->prev = list->last; list->last->next = list->first; } // 得到第i个元素的值 bool GetElem(struct list *list, int pos, ElemType *val) { if (list == NULL || list->NodeNum == 0 || pos < 1 || pos > list->NodeNum) { return false; } list->last->next = NULL; struct node *p = list->first; int i = 1; while (p) { if (i == pos) { *val = p->data; list->last->next = list->first; return true; } i++; p = p->next; } list->last->next = list->first; return false; } // 判断链表是否为空 bool ListEmpty(struct list *list) { if (list == NULL || list->NodeNum == 0) { return true; } return false; } /* 按值查找,返回地址 在链表L中查找值为e的数据元素 找到,则返回L中值为e的数据元素的地址,查找失败返回NULL */ struct node* LocateElem1(struct list *list, ElemType e) { if (list == NULL) { return NULL; } list->last->next = NULL; struct node *p = list->first; while (p && p->data != e) { p = p->next; } list->last->next = list->first; return p; } /* 按值查找,返回位置序号 在链表L中查找第一个值为e的数据元素 找到,则返回L中值为e的位置序号,查找失败返回0 */ int LocateElem2(struct list *list, ElemType e) { if (list == NULL) { return 0; } list->last->next = NULL; struct node *p = list->first; // 遍历指针 int j = 1; // 不可写成while (p->data != e && p) 原因:段错误 短路 p最后指向空 while (p && p->data != e) { p = p->next; j++; } if (p) { list->last->next = list->first; return j; } list->last->next = list->first; return 0; } // 插入——在第i个结点前插入一个值为e的新结点 bool insert_node(struct list *list, int i, ElemType e) { // 异常处理 if (list == NULL || list->NodeNum == 0 || i < 1 || i > list->NodeNum) { return false; } // 变成普通双链表 list->first->prev = NULL; list->last->next = NULL; struct node *pnew = malloc(sizeof(*pnew)); // 创建一个新结点 pnew->data = e; pnew->next = NULL; pnew->prev = NULL; struct node *p = list->first; // 遍历指针 int j = 1; while (j != i) { p = p->next; j++; } if (j == 1) { // 头插 pnew->next = list->first; list->first->prev = pnew; list->first = pnew; } else { // 中间插 pnew->next = p; pnew->prev = p->prev; p->prev->next = pnew; p->prev = pnew; } list->NodeNum++; // 链表长度加1 // 变回循环双链表 list->first->prev = list->last; list->last->next = list->first; return true; } // 删除第i个结点 bool delete_a_node(struct list *list, int i, ElemType *e) { // 特殊情况 if (list == NULL || list->NodeNum == 0 || i < 1 || i > list->NodeNum) { return false; } // 变成普通双链表 list->first->prev = NULL; list->last->next = NULL; struct node *p = list->first; // 遍历指针 int j = 1; while (j != i) { p = p->next; j++; } list->NodeNum--; // 链表长度减一 if (j == 1) { // 头删 list->first = list->first->next; if (list->first) { list->first->prev = NULL; } else { // 链表长度 == 0 list->last = NULL; } *e = p->data; // 保存被拆结点数据 p->next = NULL; free(p); } else if (p == list->last) { // 尾删 list->last = p->prev; list->last->next = NULL; *e = p->data; // 保存被拆结点数据 p->prev = NULL; free(p); } else { // 中间删 struct node *pre = p->prev; // 被删结点的前驱结点 *e = p->data; // 保存被拆结点数据 pre->next = p->next; p->next->prev = pre; p->next = NULL; p->prev = NULL; free(p); } // 如果链表不为空,变回循环双链表 if (list->NodeNum) { list->first->prev = list->last; list->last->next = list->first; } return true; }
main.c
#include "BothWithCircleLinkedListWithHead.h" int main(int argc, char *argv[]) { // struct list *list = create_list(); // 创建一个新链表,返回链表的首地址 struct list *list = create_sort_list(); // 创建一个有序新链表,返回链表的首地址 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); list = add_a_node(list, 3, 999); // 在值为3的结点前面增加一个值为999的结点 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); list = delete_node(list, 999); // 删除值为999的结点 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); update_node(list, 3, 33); // 把链表中值为3的结点的值改成33 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); reverse_list(list); // 逆置链表 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); ElemType d; if (GetElem(list, 2, &d)) { // 得到第二个元素的值 printf("第二个元素的值为:%d\n", d); } sort_list_with_head(list); //对链表进行排序 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); insert_node_order(list, 99); //有序插入99 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); if (LocateElem1(list, 33)) { // 按值查找,返回地址 printf("%d的地址: %p\n", 33, LocateElem1(list, 33)); } if (LocateElem2(list, 33)) { // 按值查找,返回位置序号 printf("%d的序号: %d\n", 33, LocateElem2(list, 33)); } if (insert_node(list, list->NodeNum, 111)) { // 插入——在第2个结点前插入一个新结点 print_list(list); // 遍历遍历 printf("链表长度为:%d\n", list->NodeNum); } while (!ListEmpty(list)) { if (delete_a_node(list, 1, &d)) { printf("第1个结点: %d被删除\n", d); print_list(list); printf("链表长度为:%d\n", list->NodeNum); } } list = destroy_list(list); // 销毁链表 return 0; }