数据结构实验01线性表.docx
《数据结构实验01线性表.docx》由会员分享,可在线阅读,更多相关《数据结构实验01线性表.docx(16页珍藏版)》请在冰豆网上搜索。
![数据结构实验01线性表.docx](https://file1.bdocx.com/fileroot1/2023-1/31/127913ca-1a8f-44c0-9b5b-c3e4d7109aa4/127913ca-1a8f-44c0-9b5b-c3e4d7109aa41.gif)
数据结构实验01线性表
《数据结构与算法》实验报告
班级学号
姓名
实验周次
实验日期
实验01:
线性表
一、实验目的
1.掌握单向链表和顺序表的特点;
2.掌握链式和顺序存储结构的基本运算;
3.掌握单向链表和顺序表的创建、插入、删除和显示表中元素等基本操作。
二、实验内容
假设一个班有N个学生(N<20),每个学生有学号、姓名、性别、分数共4个成员。
各个学生之间的逻辑关系是线性的,请采用单向链表或顺序表作为存储结构编写程序。
程序所要实现的功能如下:
①插入一个学生到线性表的指定位置,如果用户指定位置不合法,则需给出相应提示;
②按学号从线性表中查找并删除一个指定学生,如果用户指定学生不存在,则需给出提示;
③按学号查找用户指定的某个学生,找到后更改该学生的指定信息,如果未找到该学生则需给出提示;
④输出所有学生的相关信息。
程序运行的主菜单如图1-1所示。
三、实验要求
1.学号为1-20号且学号为单号的同学:
以有头结点的单向链表作为线性表的存储结构;
2.学号为21-50号且学号为单号的同学:
以无头结点的单向链表作为线性表的存储结构。
3.所有学号为双号的同学:
采用顺序表作为线性表的存储结构,线性表的预设长度为20。
4.学有余力的同学:
采用顺序表作为线性表的存储结构,但是程序可以通过realloc()函数动态扩充顺序表的长度。
四、运行结果(截图)
图1-1显示表中所有信息
图1-2插入功能
图1-3删除功能
图1-4修改功能
图1-5修改结果的显示
五、实验程序(源代码)
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
//学生结构体
typedefstruct
{
charno[10];
charname[20];
chargender;
floatscore;
}STU;
//单链表结点的结构体
typedefstructLNode
{
STUdata;//当前结点中存储的学生数据
structLNode*next;//下一个结点的地址
}LinkedNode;
//功能菜单
voidmenu()
{
printf("\n\t***********单向链表(无头结点)*************\n");
printf("\t*1插入一个学生*\n");
printf("\t*2删除一个学生*\n");
printf("\t*3修改学生信息*\n");
printf("\t*4输出所有学生信息*\n");
printf("\t*0保存数据并退出程序*\n");
printf("\t******************************************\n");
printf("\t请选择菜单项:
");
}
/*检测当前目录下是否存在文件stu.dat,如果存在,则从其中读取数据构造线性表;
否则,新建该数据文件。
*/
LinkedNode*init()
{
FILE*fp;
charflag='r';
STUstmp;
LinkedNode*head,*p,*rear;
//不带头结点的单链表,设置其头指针为空,则表示链表为空
head=NULL;
//打开文件
if((fp=fopen("stu.dat","rb"))==NULL)
{
flag='w';
if((fp=fopen("stu.dat","wb"))==NULL)
{
printf("数据文件不存在或创建文件不成功,程序异常退出!
\n");
exit(-1);
}
}
//开始读文件
if(flag=='r')
{
fread(&stmp,sizeof(STU),1,fp);
while(!
feof(fp))
{
//开辟一个结点空间
p=(LinkedNode*)malloc(sizeof(LinkedNode));
//构造结点
p->data=stmp;
p->next=NULL;
//为了保证恢复出来的链表结点顺序和当初存入的结点顺序保持一致
//将构造好的结点从尾部插入单向链表
if(NULL==head)//如果插入的是第一个结点
{
rear=p;
head=p;
}
else//如果插入的不是第一个结点
{
rear->next=p;
rear=p;
}
//再读一个学生的数据
fread(&stmp,sizeof(STU),1,fp);
}
}
//关闭文件
fclose(fp);
//返回单链表的头指针
returnhead;
}
/*输入一个学生的信息,构造一个新结点*/
LinkedNode*getNewNode()
{
LinkedNode*pNew;
//开辟一个结点空间
pNew=(LinkedNode*)malloc(sizeof(LinkedNode));
//构造结点
printf("请输入待插入学生的信息!
\n");
fflush(stdin);
printf("Pleaseinputthenum:
\t");
gets(pNew->data.no);
fflush(stdin);
printf("Pleaseinputthename:
\t");
gets(pNew->data.name);
fflush(stdin);
printf("Pleaseinputthesex:
\t");
scanf("%c",&(pNew->data.gender));
fflush(stdin);
printf("Pleaseinputthescore:
\t");
scanf("%f",&(pNew->data.score));
pNew->next=NULL;
returnpNew;
}
/*插入一个学生到不带头结点的单链表中*/
voidinsert(LinkedNode*&head)//调用过程中head有可能被改变,因此需用指针的引用参数,或者使用二级指针
{
intpoi,count;
LinkedNode*pre,*pNew;//pre指向插入位置的直接前驱结点,pNew用于开辟新结点空间
printf("请输入待插入学生的位置:
\n");
scanf("%d",&poi);
if(1==poi)//如果插入到第一个位置(此时需要改变head的值,因此需要单独讨论)
{
pNew=getNewNode();
//插入新结点到单向链表中的第一个结点之前
pNew->next=head;
head=pNew;//新结点成为新的第一个学生结点
}
else//如果插入的不是第一个位置
{
pre=head;//先让pre指向第一个学生结点
count=1;//第一个结点的报数为1
//当未到链表尾部,并且报数未到第poi-1个学生结点(即插入点的直接前驱)时
while(pre!
=NULL&&count{
pre=pre->next;
count++;
}
//如果找到了正确的插入位置
if(count==poi-1&&pre!
=NULL)
{
pNew=getNewNode();//输入插入学生信息,构造一个新的结点
//插入新结点到单向链表中pre所指结点之后
pNew->next=pre->next;
pre->next=pNew;
}
else//如果插入位置不合法
{
printf("您输入的插入位置不合法!
\n");
}
}
}
/*从不带头结点的单链表中删除一个指定学生*/
voiddel(LinkedNode*&head)//调用过程中head有可能被改变,因此需用指针的引用参数,或者使用二级指针
{
if(NULL!
=head)
{
charno[10];
intflag=0;//flag==0表示未删除;flag==1表示已经删除
LinkedNode*pre,*q;//pre指向待删除结点的直接前驱,q指向待删除结点
fflush(stdin);
printf("请输入待删除学生的学号:
\n");
scanf("%s",no);
if(!
strcmp(head->data.no,no))//如果待删除的结点是第一个结点
{
q=head;
head=head->next;
printf("学号为%s的学生已经成功删除!
\n",q->data.no);
free(q);//先提示,后释放
flag=1;
}
else//如果待删除的结点不是第一个结点
{
//pre始终要指向待删除结点的直接前驱,先让其指向整个链表中的第一个学生结点
pre=head;
while(NULL!
=pre->next)
{
if(!
strcmp(pre->next->data.no,no))//如果找到了待删除结点的直接前驱
{
q=pre->next;//q指向待删除结点
pre->next=q->next;//先让q所指结点从链表中断开
printf("学号为%s的学生已经成功删除!
\n",q->data.no);
free(q);//先提示,后释放
flag=1;
break;
}
else
pre=pre->next;
}
}
if(0==flag)
printf("未找到您要删除的学生!
\n");
}
else
{
printf("当前单链表为空,没有学生数据可供删除!
\n");
}
}
/*查找指定学生,并修改其信息*/
voidmodify(LinkedNode*&head)//调用过程中head有可能被改变,因此需用指针的引用参数,或者使用二级指针
{
if(NULL!
=head)
{
charno[10];
intchoice,flag=0;
LinkedNode*p;
//p最终要指向待修改的学生结点,所以先让其指向第一个学生结点
p=head;
printf("请输入待修改学生的学号:
\n");
scanf("%s",no);
while(p!
=NULL)
{
if(!
strcmp(p->data.no,no))//如果找到待修改的学生
{
while
(1)
{
printf("当前学生的信息如下:
\n");
printf("1--学号:
%s\n",p->data.no);
printf("2--姓名:
%s\n",p->data.name);
printf("3--性别:
%c\n",p->data.gender);
printf("4--分数:
%.1f\n",p->data.score);
printf("请选择修改信息项的编号(输入0完成修改):
");
fflush(stdin);
scanf("%d",&choice);
switch(choice)
{
case1:
fflush(stdin);
printf("请输入修改后的学号:
");
scanf("%s",p->data.no);
break;
case2:
fflush(stdin);
printf("请输入修改后的姓名:
");
scanf("%s",p->data.name);
break;
case3:
fflush(stdin);
printf("请输入修改后的性别:
");
scanf("%c",&p->data.gender);
break;
case4:
fflush(stdin);
printf("请输入修改后的分数:
");
scanf("%f",&p->data.score);
break;
case0:
flag=1;//flag设置为1是为了跳出内层的while
(1)循环
break;
default:
printf("不存在此选项,请重新输入信息项的编号!
\n");
}
choice=-1;//输入错误的信息项编号或者未输入信息项编号
if(1==flag)
break;
}
return;//内层的while
(1)循环结束,说明修改完成,直接返回即可
}
else
p=p->next;//当前结点不是待修改的学生,继续查看链表中的下一个结点
}
//如果前面一直都未能通过return;语句返回,则说明链表中没有要找的学生
printf("当前单链表中没有学号为%s的学生!
\n",no);
}
else
{
printf("当前单链表为空,没有学生数据可供修改!
\n");
}
}
/*显示所有学生的信息*/
voidshowAll(LinkedNode*head)
{
LinkedNode*p;
inti;
//先让p指向第一个学生结点
p=head;
if(head)
{
printf("单链表中所有学生的信息如下!
\n");
printf("%5s%11s%21s%7s%9s\n","序号","学号","姓名","性别","成绩");
i=1;
while(NULL!
=p)
{
printf("%5d%11s%21s%7c%9.1f\n",i,p->data.no,p->data.name,p->data.gender,p->data.score);
p=p->next;
i++;
}
}
else
printf("单链表为空!
\n");
}
/*保存所有学生的信息到文件*/
voidsave(LinkedNode*head)
{
FILE*fp;
LinkedNode*p;
//打开文件
if((fp=fopen("stu.dat","wb"))==NULL)
{
printf("数据文件打开失败,保存不成功,程序异常退出!
");
exit(-1);
}
//开始写文件
p=head;
while(p!
=NULL)
{
fwrite(&(p->data),sizeof(STU),1,fp);
p=p->next;
}
//关闭文件
fclose(fp);
printf("单链表中的所有数据已经成功写入文件!
\n");
}
voidmain()
{
intchoice=-1;
LinkedNode*head;
head=init();
while
(1)
{
menu();
fflush(stdin);
scanf("%d",&choice);
switch(choice)
{
case1:
insert(head);
break;
case2:
del(head);
break;
case3:
modify(head);
break;
case4:
showAll(head);
break;
case0:
save(head);
exit(0);
break;
default:
printf("\t您输入的菜单项不存在,请重新选择!
\n");
}
choice=-1;
}
}