实验任务
(1) 掌握单链表结构及其 C 语言实现;
(2) 掌握插入、删除等基本算法;
(3) 掌握单链表的基本应用(将两个有序线性表合并为一个有序表)。
实验内容
- 使用 C 语言实现单链表的类型定义与算法函数;
- 编写 main()函数,合理调用函数实现以下功能:
- 创建 2 个单链表 L1、L2(带头结点,用于存储表长);
- 初始化 L1 数据并显示(斐波拉契序列前 2-11 项):1、2、、…、89;
- 随机产生 L2 数据 10 个:
- 第 1 个数为 4,其后每个数字比其前趋随机增加1~9,显示L2 内容
- 附加分 20:再用洗牌算法随机打乱(10 次)L2 中的数据,显示L2的内容
- 将 L2 中的结点按从前往后的顺序一个一个有序合并到L1 中(即每次都将L2中的首元结点摘下链入 L1 中正确位置,完成后 L2 成为空表),显示L1的内容;
- 随机删除 L1 中第 1~20 个元素,显示 L1 的内容;
- 随机产生 1 个[1, 100]之间的数字插入到 L1 中并保持有序,显示L1的内容;
- 销毁 L1 和 L2,即将所有结点空间归还系统。
实验源码
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <time.h>#define NUM_L1 10
#define NUM_L2 10typedef enum {ERROR,OK
} status;typedef enum {FALSE,TRUE
} boolean;typedef int ElemType;typedef struct LNode { // 链表的定义ElemType data;struct LNode *next;
} LNode, *LinkList;status InitList(LinkList list); // 链表的初始化void PrintList(LinkList list); // 打印链表void Fibonacci(LinkList list, int length); // 创建 L1void RandomNumber(LinkList list, int num); // 创建 L2void knuthShuffle(LinkList list, int num); // 洗牌算法(交换值的方式)void swapInt(ElemType *elem1, ElemType *elem2); // 辅助洗牌算法 交换元素ElemType *GetElem(LinkList list, int num); // 辅助洗牌算法 取值void BubbleSort(LinkList list); // 冒泡排序(值交换)void MergeList_L(LinkList list1, LinkList list2); // L2 合并到 L1 并保持有序status DeleteElem(LinkList list, int i); // 随机删除 L1 中的第i个元素status InsertElem(LinkList list, ElemType randElem); // 随机插入一个元素到 L1中 并保持有序boolean IsEmpty(LinkList list); // 判断链表是否为空 [辅助插入]status InitList(LinkList list) {list = (LinkList) malloc(sizeof(LNode));if (list == NULL) {return ERROR;}list->next = NULL;list->data = 0;return OK;
}void PrintList(LinkList list) {LNode *temp;int count = 0;printf("->{%2d}", list->data);for (temp = list->next; temp != NULL; temp = temp->next) {printf("->(%2d)", temp->data);if (++count % 10 == 0 && count != list->data) {printf("\n ");}}printf("\n");
}void Fibonacci(LinkList list, int length) {int num1 = 0;int num2 = 1;LNode *temp, *tail;tail = list;for (int i = 1; i <= length; i++) {temp = (LinkList) malloc(sizeof(LNode));if (i % 2 != 0) {num1 += num2;temp->data = num1;} else {num2 += num1;temp->data = num2;}tail->next = temp;tail = temp;}tail->next = NULL;list->data = length;
}void RandomNumber(LinkList list, int num) {LNode *temp, *tail;ElemType tElem; // 临时存储数据 tempElemtail = list;for (int i = 0; i < num; i++) {temp = (LinkList) malloc(sizeof(LNode));if (i != 0) {temp->data = tElem + rand() % 9 + 1;} else {temp->data = 4;}tElem = temp->data;tail->next = temp;tail = temp;}tail->next = NULL;list->data = num;
}void knuthShuffle(LinkList list, int num) {for (int i = num - 1; i >= 1; i--) {swapInt(GetElem(list, i), GetElem(list, (rand() % (i + 1))));}
}void swapInt(ElemType *elem1, ElemType *elem2) {ElemType temp;temp = *elem1;*elem1 = *elem2;*elem2 = temp;
}ElemType *GetElem(LinkList list, int num) {LNode *temp = list->next;int j = 1;while (temp && j < num) {temp = temp->next;++j;}return &(temp->data);
}void BubbleSort(LinkList list) {LNode *pA, *pB, *pTail = NULL;LNode *pHead = list->next;while (pTail != pHead) {pB = pHead;int count = -1;while (pB->next != pTail) {pA = pB->next;if (pA->data < pB->data) {ElemType temp = pA->data;pA->data = pB->data;pB->data = temp;count++;}pB = pB->next;}if (count == -1) {return;}pTail = pB;}
}void MergeList_L(LinkList list1, LinkList list2) {BubbleSort(list2);LNode *pL1, *pL2, *pL3;pL1 = list1->next;pL2 = list2->next;pL3 = list1;while (pL1 && pL2) {if (pL1->data <= pL2->data) {pL3->next = pL1;pL3 = pL1;pL1 = pL1->next;} else {pL3->next = pL2;pL3 = pL2;pL2 = pL2->next;}}pL3->next = pL1 ? pL1 : pL2;list1->data = list1->data + list2->data;
}status DeleteElem(LinkList list, int i) {LNode *pL = list, *temp;int j = 1;while (pL->next && j < i) {pL = pL->next;++j;}while (!(pL->next) || j > i) {return ERROR;}temp = pL->next;pL->next = temp->next;free(temp);list->data--;return OK;
}status InsertElem(LinkList list, ElemType randElem) {if (IsEmpty(list) || randElem < 1 || randElem > 100) {return ERROR;}LNode *temp;temp = (LinkList) malloc(sizeof(LNode));temp->next = NULL;temp->data = randElem;LNode *pL = list->next;while (pL->next != NULL) {pL = pL->next;}pL->next = temp;list->data++;BubbleSort(list);return OK;
}boolean IsEmpty(LinkList list) {if (list->next == NULL) {return TRUE;} else {return FALSE;}
}/*** <h2>单链表实验</h2>* return 0*/
int main() {LNode L1, L2;srand(time(NULL));printf("=========================== 单链表编程实践 ===========================\n");if (InitList(&L1) == OK) {printf("【单链表L1已生成】\n");Fibonacci(&L1, NUM_L1);printf("L1");PrintList(&L1);}if (InitList(&L2) == OK) {printf("【单链表L2已生成】\n");RandomNumber(&L2, NUM_L2);printf("L2");PrintList(&L2);}printf("【Knuth洗牌算法随机打乱L2】\n");knuthShuffle(&L2, NUM_L2);printf("L2");PrintList(&L2);printf("【单链表L2有序合并到L1】\n");MergeList_L(&L1, &L2);printf("L1");PrintList(&L1);int randNum_10 = rand() % 10 + 1;printf("【随机删除L1中第%d个元素】\n", randNum_10);DeleteElem(&L1, randNum_10);printf("L1");PrintList(&L1);ElemType randNum_100 = rand() % 100 + 1;printf("【随机产生%d插入到L1中】\n", randNum_100);InsertElem(&L1, randNum_100);printf("L1");PrintList(&L1);return 0;
}