实验内容
编程实现链表下教材第二章定义的线性表的基本操作,最好用菜单形式对应各个操作,使其编程一个完整的小软件。注意,每个功能模块一定要考虑非法的情况,并作出相应的提示,例如:求前驱,要分别能够测试第一个元素的前驱、其他正常的元素的前驱、输入一个在表中不存在的元素求其前驱,这三种情况应给出相应的提示语和结果值;插入和删除时要考虑插入或删除的位置是否合法等。
实验要求:
菜单项包括:
1.初始化或重置链表
2.销毁链表
3.清空链表
4.链表长度
5.指定位置的元素值
6.链表已存在元素的位序
7.求输入元素的直接前驱
8.求输入元素的直接后继
9.在第i个位置插入一个元素
10.删除第i个元素
11.输出有的链表元素
12.初始化并用头插法(或尾插法)输入元素
13.实现单链表的逆序存放
要求:所有的提示语和输出语句不允许出现在自定义的函数中,只能在main函数中出现提示语。
注:销毁链表时需要循环释放每个结点所占用的空间。
注:求前驱是指,输入一个元素值(而不是位置),求该元素在顺序表中的直接前驱元素值。求后继是指:输入一个元素值(而不是位置),求该元素在顺序表中的直接后继元素值。
一、设计思想
- 结构体的定义:首先,这段代码定义了一个叫LNode的结构体,表示链表节点。每个节点都包含一个data(后续我们会将一些值储存在这里)和一个指向下一个节点的指针。此外,还有一个is_initialized标志,用于标识该节点是否被初始化。
- 链表操作的函数:
- Initialize_reset_linklist:这个函数用于初始化或重置链表。它首先分配内存给头结点,然后设置头结点的next指针指向NULL,最后返回该头结点。
- Destroy_linklist:这个函数会销毁整个链表,包括头结点。它会遍历链表,释放每个节点占用的内存。
- Clear_linklist:清空链表中除了头结点之外的所有节点。
- Length_linklist:返回链表的长度。
- Data_linklist:根据给定位置查找元素。
- Order_linklist:查找某元素在链表中的位置。
- Before_linklist和After_linklist:分别用于查找某元素的前驱和后继。
- Insert_linklist:在某个位置插入新的元素。
- Delete_linklist:删除某个位置的元素。
- Print_linklist:遍历链表并打印所有元素。
- Initialize_Tail_interpolation_linklist:采用尾插法初始化链表。
- Reverse_linklist:将链表逆序存放。
二、主要源代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdlib.h>//malloc需用库函数
#include<stdio.h>
typedef int Elemtype;
typedef struct LNode
{
Elemtype data;
struct LNode* next;
int is_initialized;
}LNode, * Linklist;
Linklist Initialize_reset_linklist()//1
{
LNode* p, * q, * head;
head = (LNode*)malloc(sizeof(LNode));//为头结点分配内存
if (head == NULL) {
printf("内存分配失败!\n");
return NULL;
}
head->next = NULL;//头结点的下一个节点为空
q = head;//q指针初始化
head->is_initialized = 1;
printf("初始化完成!\n");
return head;//返回头结点的指针
}
void Destroy_linklist(LNode* head)//2 包含单向链表的头结点在内,销毁单向链表的所有结点
{
if (head == NULL || !(head->is_initialized))
{
printf("链表还未初始化,无法销毁!\n");
return;
}
LNode* p = head;
LNode* q = NULL;//声明两个指针变量p和q
while (p != NULL)
{
q = p;//分别指向链表的头节点和当前节点
p = p->next;
free(q);//释放q指向的节点的内存空间
q = NULL;
}
printf("销毁成功!\n");
}
void Clear_linklist(LNode* head)//3 清空除了头结点之外的所有结点的数据域和指针域
{
if (head == NULL || !(head->is_initialized))
{
printf("链表还未初始化,无法清空!\n");
return;
}
LNode* p = head->next;
LNode* temp = head;
LNode* q = NULL;
while (p != NULL)
{
q = p;
p = p->next;
free(q);
q = NULL;
}
printf("清空成功!\n");
}
int Length_linklist(const LNode* head)// 4
{
if (head == NULL || !(head->is_initialized))
{
printf("链表还未初始化,无法计算长度!\n");
return -1;
}
int length = head->data;
return length;
}
void Data_linklist(const LNode* head)// 5
{
if (head == NULL || !(head->is_initialized))
{
printf("链表还未初始化,无法查找!\n");
return;
}
int pos = 0;
printf("请输入你要查找链表中的第几位元素:\n");
if (scanf("%d", &pos) != 1) {
printf("输入错误!\n");
return;
}
LNode* p;
p = head;
if (pos > 0 && pos <= head->data)
{
int i = 1;
while (i < pos + 1)
{
p = p->next;
i++;
}
printf("第%d位元素的值为:%d\n", pos, p->data);
}
else
printf("输入位置有误,请重新输入!\n");
}
void Order_linklist(const LNode* head)//6
{
if (head == NULL || !(head->is_initialized))
{
printf("链表还未初始化,无法查找!\n");
return;
}
printf("请输入你想查询次序的元素:\n");
Elemtype elem = 0;
if (scanf("%d", &elem) != 1) {
printf("输入错误!\n");
return;
}
LNode* p = head->next;
int i = 1;
while (p != NULL)
{
if (p->data == elem)
{
printf("元素%d在链表中的位置是:%d\n", elem, i);
return;
}
i++;
p = p->next;
}
printf("元素%d在链表中不存在。\n", elem);
}
void Before_linklist(const LNode* head)//7
{
if (head == NULL || !(head->is_initialized))
{
printf("链表还未初始化,无法查找!\n");
return;
}
printf("请输入元素的值,程序将输出该元素的直接前驱元素值\n");
int temp = 0;
int flag = 1;
if (scanf("%d", &temp) != 1) {
printf("输入错误!\n");
return;
}
int temp_old = 0;
LNode* p = head->next;
while (flag)
{
if (temp == p->data)
{
flag = 0;
}
else
{
temp_old = p->data;
p = p->next;
}
}
printf("该元素的直接前驱元素值为:%d\n", temp_old);
}
void After_linklist(const LNode* head)//8
{
if (head == NULL || !(head->is_initialized))
{
printf("链表还未初始化,无法查找!\n");
return ;
}
printf("请输入元素的值,程序将输出该元素的直接后继元素值\n");
int temp = 0;
if (scanf("%d", &temp) != 1) {
printf("输入错误!\n");
return ;
}
LNode* p = head->next;
while (p != NULL)
{
if (temp == p->data)
{
if (p->next != NULL)
{
printf("该元素的直接后继元素值为:%d\n", p->next->data);
}
else {
printf("该元素没有直接后继元素!\n");
return ;
}
}
p = p->next;
}
}
void Insert_linklist(LNode* head)//9
{
if (head == NULL || !(head->is_initialized))
{
printf("链表还未初始化,无法插入!\n");
return;
}
printf("请输入你要插入元素的位置:\n");
int pos = 0;
if (scanf("%d", &pos) != 1) {
printf("输入错误!\n");
return;
}
printf("请输入你要插入的元素:\n");
Elemtype elem;
if (scanf("%d", &elem) != 1) {
printf("输入错误!\n");
return;
}
LNode* p = head;
int i = 1;
while (p != NULL && i < pos)
{
p = p->next;
i++;
}
if (p == NULL && i < pos) {
printf("插入位置超出链表长度!\n");
return;
}
LNode* d = (LNode*)malloc(sizeof(LNode));// 创建新节点
if (d == NULL) {
printf("内存分配失败!\n");
return;
}
d->data = elem;
d->next = p->next;
p->next = d;
printf("插入成功!\n");
}
void Delete_linklist(LNode* head)//10
{
if (head == NULL || !(head->is_initialized))
{
printf("链表还未初始化,无法删除!\n");
return;
}
printf("请输入你要删除的元素的位置:\n");
int pos = 0;
if (scanf("%d", &pos) != 1) {
printf("输入错误!\n");
return;
}
LNode* p = head;
int i = 0;
while (p != NULL && i < pos - 1)
{
p = p->next;
i++;
}
if (p->next != NULL)
{
LNode* q = p->next;
p->next = q->next;
free(q);
q = NULL;
}
printf("删除成功!\n");
}
void Print_linklist(const LNode* head)//11
{
if (head == NULL || !(head->is_initialized))
{
printf("链表还未初始化,无法输出!\n");
return;
}
LNode* p = head->next;
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
Linklist Initialize_Tail_interpolation_linklist()
{
LNode* p, * q, * head;
head = (LNode*)malloc(sizeof(LNode)); //为头结点分配内存
if (head == NULL) {
printf("内存分配失败!\n");
return NULL;
}
head->next = NULL; //头结点的下一个节点为空
q = head; //q指针初始化
printf("请输入要创建的链表长度:\n");
int length = 0;
if (scanf("%d", &length) != 1) {
printf("输入错误!\n");
return NULL;
}
head->data = length; //将链表的长度存储在头结点的数据域之中
for (int i = 0; i < length; i++)
{
p = (LNode*)malloc(sizeof(LNode)); //对每个新节点都分配空间
if (p == NULL) {
printf("内存分配失败!\n");
return NULL;
}
printf("请输入链表的第%d个元素的数据:\n", i + 1);
if (scanf("%d", &(p->data)) != 1) {
printf("输入错误!\n");
return NULL;
}
p->next = NULL; //新节点的下一个节点设置为NULL
q->next = p; //插入新节点
q = p; //更新q节点
}
printf("创建成功!\n");
return head; //返回头结点的指针
}
Linklist Reverse_linklist(LNode* head)//13
{
if (head == NULL || !(head->is_initialized))
{
printf("链表还未初始化,无法逆序!\n");
return NULL;
}
LNode* p = head->next;
LNode* q = NULL;
LNode* r = NULL;
while (p != NULL)
{
r = q;
q = p;
p = p->next;
q->next = r;
}
head->next = q;
printf("逆序成功!\n");
Print_linklist(head);
return head;
}
void menu()
{
printf("****------------------指令菜单-------------------****\n");
printf("**** 1.初始化或重置链表 ****\n");
printf("**** 2.销毁链表 ****\n");
printf("**** 3.清空链表 ****\n");
printf("**** 4.链表长度 ****\n");
printf("**** 5.指定位置的元素值 ****\n");
printf("**** 6.链表已存在元素的位序 ****\n");
printf("**** 7.求输入元素的直接前驱 ****\n");
printf("**** 8.求输入元素的直接后继 ****\n");
printf("**** 9.在第i个位置插入一个元素 ****\n");
printf("**** 10.删除第i个元素 ****\n");
printf("**** 11.输出有的链表元素 ****\n");
printf("**** 12.初始化并用头插法(或尾插法)输入元素 ****\n");
printf("**** 13.实现单链表的逆序存放 ****\n");
}
int main()
{
int input = 0;
int pos;
Linklist linklist = NULL;
menu();
do
{
printf("请输入要选择的指令:\n");
scanf("%d", &input);
switch (input)
{
case 1:
linklist = Initialize_reset_linklist();
break;
case 2:
Destroy_linklist(linklist);
linklist = NULL;
break;
case 3:
Clear_linklist(linklist);
break;
case 4:
if (Length_linklist(linklist) >= 0)
printf("链表长度:%d\n", Length_linklist(linklist));
break;
case 5:
Data_linklist(linklist);
break;
case 6:
Order_linklist(linklist);
break;
case 7:
Before_linklist(linklist);
break;
case 8:
After_linklist(linklist);
break;
case 9:
Insert_linklist(linklist);
break;
case 10:
Delete_linklist(linklist);
break;
case 11:
Print_linklist(linklist);
break;
case 12:
linklist = Initialize_Tail_interpolation_linklist();
break;
case 13:
linklist = Reverse_linklist(linklist);
break;
default:
printf("无效的指令,请重新输入!\n");
break;
}
} while (input != 0);
return 0;
}
验收/测试用例
|