实 验 二 报 告
一、实验目的
1.熟练掌握链表的结构类型定义、特点。
2.熟练掌握链表的基本操作算法的实现及其算法时间复杂度的分析。
3.掌握循环链表、双向链表的结构类型定义及其基本操作算法。掌握链表的应用。
二、实验内容
1.请编写一个完整的程序,并上机实现如下操作。
(1)产生20个1~200的随机整数,并依次保存到带头结点的单链表中。
(2)计算单链表的长度,并将结果存放在头结点的数据域中,然后输出单链表。
(3)从单链表中删除与给定值 x 相等的所有结点,然后输出单链表。
(4)在(3)题的基础上将单链表降序排列,并输出结果。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// 定义单链表节点结构
typedef struct Node {
int data;
struct Node *next;
} Node;
// 定义带头结点的单链表结构
typedef struct {
Node *head;
} LinkList;
// 创建新节点
Node* createNode(int data) {
Node *newNode = (Node*)malloc(sizeof(Node));
if (!newNode) {
exit(-1);
}
newNode->data = data;
newNode->next = NULL;
return newNode;
}
// 初始化带头结点的单链表
void initLinkList(LinkList *L) {
L->head = createNode(0); // 创建头结点,数据域可以存长度信息
}
// 产生随机整数并保存到单链表
void generateRandom(LinkList *L) {
srand((unsigned)time(NULL));
for (int i = 0; i < 20; ++i) {
int randomNumber = rand() % 200 + 1;
Node *newNode = createNode(randomNumber);
newNode->next = L->head->next; // 插入到头结点之后
L->head->next = newNode;
}
}
// 计算单链表的长度
int getLength(LinkList *L) {
int length = 0;
Node *current = L->head->next;
while (current) {
length++;
current = current->next;
}
L->head->data = length; // 将长度存放在头结点的数据域中
return length;
}
// 输出单链表
void printList(LinkList *L) {
Node *current = L->head->next;
while (current) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
// 删除与给定值相等的节点
void deleteWithValue(LinkList *L, int x) {
Node *current = L->head;
while (current->next) {
if (current->next->data == x) {
Node *temp = current->next;
current->next = temp->next;
free(temp);
} else {
current = current->next;
}
}
}
// 降序排列单链表
void sortDescending(LinkList *L) {
Node *current = L->head->next;
int tempData;
while (current) {
Node *next = current->next;
while (next) {
if (current->data < next->data) {
tempData = current->data;
current->data = next->data;
next->data = tempData;
}
next = next->next;
}
current = current->next;
}
}
int main() {
LinkList L;
initLinkList(&L);
// (1) 产生随机整数并保存到单链表
generateRandom(&L);
// (2) 计算单链表的长度并输出
printf("Length of the list: %d\n", getLength(&L));
printList(&L);
// (3) 删除与给定值相等的节点
int x;
printf("Enter the value to delete: ");
scanf("%d", &x);
deleteWithValue(&L, x);
printf("List after deleting value %d:\n", x);
printList(&L);
// (4) 降序排列单链表并输出
sortDescending(&L);
printf("List after sorting in descending order:\n");
printList(&L);
// 释放链表内存
Node *temp;
while (L.head->next) {
temp = L.head->next;
L.head->next = temp->next;
free(temp);
}
free(L.head);
return 0;
}
- 用带头结点的单链表表示学生成绩表,请编写程序,完成实验1第(3)题相应的任务。
#include <stdio.h>
#include <stdlib.h> // 包含stdlib.h以使用malloc和free
// 学生结构体定义
typedef struct Student {
int id;
char name[50];
float score;
} Student;
// 学生链表节点
typedef struct StudentNode {
Student data;
struct StudentNode *next;
} StudentNode;
// 带头结点的学生链表
typedef struct {
StudentNode *head;
} StudentList;
// 删除指定ID的学生
void deleteStudentById(StudentList *L, int id) {
StudentNode *current = L->head->next;
StudentNode *prev = L->head;
while (current) {
if (current->data.id == id) {
prev->next = current->next; // 跳过当前节点
free(current); // 释放当前节点的内存
break;
}
prev = current;
current = current->next;
}
}
int main() {
// 初始化带头结点的学生链表
StudentList list;
list.head = (StudentNode*)malloc(sizeof(StudentNode)); // 分配头结点
if (list.head == NULL) {
exit(-1);
}
list.head->next = NULL; // 初始化链表为空
// 创建一些学生节点并添加到链表中
Student students[] = {
{1, "Alice", 89.5},
{2, "Bob", 92.0},
{3, "Cathy", 78.5},
{4, "David", 88.0},
{5, "Ella", 91.5}
};
int numStudents = sizeof(students) / sizeof(students[0]);
for (int i = 0; i < numStudents; ++i) {
StudentNode *newNode = (StudentNode*)malloc(sizeof(StudentNode));
if (newNode == NULL) {
exit(-1);
}
newNode->data = students[i];
newNode->next = list.head->next;
list.head->next = newNode;
}
// 打印原始链表
printf("Original list:\n");
StudentNode *current = list.head->next;
while (current) {
printf("ID: %d, Name: %s, Score: %.2f\n", current->data.id, current->data.name, current->data.score);
current = current->next;
}
printf("\n");
// 删除ID为3的学生
int idToDelete = 3;
deleteStudentById(&list, idToDelete);
// 打印修改后的链表
printf("List after deleting student with ID %d:\n", idToDelete);
current = list.head->next;
while (current) {
printf("ID: %d, Name: %s, Score: %.2f\n", current->data.id, current->data.name, current->data.score);
current = current->next;
}
printf("\n");
// 释放链表内存
while (list.head && list.head->next) {
StudentNode *temp = list.head->next;
list.head->next = temp->next;
free(temp);
}
free(list.head); // 释放头结点
return 0;
}
三、实验心得:
在本次实验中,我深入研究了链表的结构类型定义和特点。链表是一种基本的数据结构,其特点在于具有灵活的动态内存分配和插入、删除操作的高效性。通过实践操作,我熟练掌握了链表的定义和特点,对其内部指针关系有了更深入的理解。
其次,我通过实验实现了链表的基本操作算法,包括插入、删除、查找等操作,并对这些算法的时间复杂度进行了分析。我深入理解了链表操作算法的实现原理,能够准确评估算法的效率和性能。
此外,我还学习了循环链表和双向链表的结构类型定义以及基本操作算法。循环链表和双向链表在特定场景下具有优势,能够更灵活地应对实际问题的需求。通过实践操作,我掌握了这两种链表的操作方法,并能够根据需求合理选择使用哪种类型的链表。
最后,我意识到链表在实际应用中的重要性。在许多场景下,链表可以作为一种高效的数据结构,如实现栈、队列等其他数据结构,或者用于管理动态内存分配等。通过本次实验的学习,我深化了对链表的理解,提升了算法设计和实现能力,为今后在数据结构和算法领域的学习和研究奠定了坚实基础。