1.1 问题描述
为了增强对单链表的熟悉,能够更加熟练地运用单链表,编写了一个单链表重复元素的删除程序。通过对该程序的实现,使我更加熟悉单链表的实现原理。
1.2 问题分析
用子函数实现单链表的初始化、尾插法建立单链表、重复元素的删除、输出单链表、置空单链表的功能,主函数其调用功能,功能菜单进行选择。
1.3 设计分析
本次实验设计主要是增强对单链表的熟悉,能够更加熟练地运用单链表。
1.4 设计部分
写出本次实验的详细设计方案。
将学生信息的单链表的初始化、尾插法建立单链表、重复元素的删除、输出单链表、置空单链表分别写五个子函数,每执行完一个功能后,程序将会重新显示菜单。
代码如下:
#include<stdio.h>
#include<stdlib.h >
typedef int elemtype; //节点的数据类型,设为整型
typedef struct node //定义单链表节点类型
{
elemtype data; //节点的数据域
struct node *next; //节点的指针域
}LinkList; //单链表的类型名为 LinkList
LinkList *head; //head 是指向单链表类型LinkList的指针变量
//初始化单链表
LinkList *Init_LinkList()
{
LinkList *head;
head = (LinkList*)malloc(sizeof(LinkList)); //生成头结点指针
if (head == NULL) //如果申请空间失败,返回空指针
{
printf("初始化失败!\n");
return 0;
}
else
{
printf("初始化成功!\n");
return head;
}
}
//尾插法创建带头结点单链表的函数
LinkList *Create_LinkListR(LinkList*head) //尾插法创建带头结点单链表的函数
{
elemtype ix;
LinkList *p, *tail; //*head,tail分别为头指针和尾指针
head->next = NULL; //置头结点指针域为空
tail = head; //尾指针域指向头结点
printf("请输入数据直到输入0结束:"); //
scanf("%d", &ix); //输入第一个数据
while (ix != 0) //输入数据,0为结束标志
{
p = (LinkList*)malloc(sizeof(LinkList));//生成新结点
if (p == NULL) //如果申请空间失败,返回主调函数
{
printf("新结点申请空间失败,无法继续建立单链表!\n");
return head;
}
p->data = ix; //为新结点数据域赋值
tail->next = p; //修改尾结点指针域
tail = p; //修改尾指针
tail->next = NULL; //将尾结点的指针域置为空
scanf("%d", &ix); //读入下一个数据
}
printf("单链表建立成功!\n");
return head; //返回头结点指针
}
//单链表的删除 删除后继结点
int DeleteAfter_LinkList(LinkList *p) //单链表的删除 删除后继结点 删除p的后继结点,成功返回1,否则返回0
{
LinkList *r;
if (!p)
{
return 0;
}
r = p->next;
if (!r)
{
return 0;
}
p->next = r->next; //将结点r从链表上摘除
free(r); //释放结点占用的内存空间
return 1;
}
//单链表的遍历
int Print_LinkList(LinkList*head) //单链表的遍历
{
LinkList *p = head->next;
if (p == NULL) //链表为空,返回值为0
{
printf("单链表为空!\n");
return 0;
}
while (p != NULL) //当前结点不为空
{
printf("%d\n", p->data); //输出当前结点的数据
p = p->next; //移动指针指向下一个结点
}
return 1;
}
//重复元素的删除
void Del_LinkList(LinkList *head)
{
LinkList *p, *r, *t, *n;
p = head;
while (p->next != NULL)
{
t = p;
n = p;
r = p->next;
p = p->next;
while (r != NULL)
{
if (t->data == r->data)
{
n->next = r->next;
r = r->next;
}
else
{
n = r;
r = r->next;
}
}
}
printf("重复元素删除成功!\n");
}
//置空表
LinkList *SetNull_LinkList(LinkList *head) //置空表
{
while (head->next)
{
DeleteAfter_LinkList(head); //依次删除每个结点
}
printf("单链表置空成功!\n");
return head;
}
//菜单界面
void menu()
{
system("cls");
printf("\n");
printf("\t\t---------------欢迎使用单链表的基本操作------------------\n");
printf("\t\t|\t\t a 初始化单链表 \t\t|\n");
printf("\t\t|\t\t b 采用尾插法建立单链表 \t\t|\n");
printf("\t\t|\t\t c 重复元素的删除 \t\t|\n");;
printf("\t\t|\t\t d 输出单链表 \t\t|\n");
printf("\t\t|\t\t e 置空单链表 \t\t|\n");
printf("\t\t|\t\t f 退出系统 \t\t|\n");
printf("\t\t---------------------------------------------------------\n");
printf("\t\t请选择(a-f):");
}
int main()
{
LinkList *head;
int quit = 0;
char select;
while (1)
{
menu(); //调用子函数
scanf("%c", &select);
switch (select)
{
case 'a': head = Init_LinkList(); break;//初始化单链表
case 'b': Create_LinkListR(head); break; //采用尾插法建立单链表
case 'c': Del_LinkList(head); break;//重复元素的删除
case 'd': Print_LinkList(head); break;//输出单链表
case 'e': SetNull_LinkList(head); break;//置空单链表
case 'f': quit = 1; break;
default:printf("请输入a~f之间的数字\n"); break;
}
if (quit == 1)
{
break;
}
printf("按任意键返回主菜单!\n");
getchar(); //提取到缓冲区中的回车键
getchar(); //起到暂停的作用
printf("程序结束!\n");
}
return 0;
}