实验任务
(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 10
typedef 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); // 创建 L1
void RandomNumber(LinkList list, int num); // 创建 L2
void 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; // 临时存储数据 tempElem
tail = 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;
}