数据结构实验报告.docx
《数据结构实验报告.docx》由会员分享,可在线阅读,更多相关《数据结构实验报告.docx(89页珍藏版)》请在冰豆网上搜索。
![数据结构实验报告.docx](https://file1.bdocx.com/fileroot1/2023-2/3/78bb248a-da47-491e-a8e0-3dcb1c9e2c88/78bb248a-da47-491e-a8e0-3dcb1c9e2c881.gif)
数据结构实验报告
数据结构实验
所属学院及班级:
信息工程学院计算机科学与技术091班
学生姓名:
学生学号:
时间:
2010-3至2010-6
实验1:
C语言基础练习
姓名:
学号:
专业班级:
计算机科学与技术091班
一、实验目的
对C语言的复习,增强学生对结构体数组和指针的学习,尤以结构体的应用和指针的操作作为重点。
二、问题描述
1、构造一个学生结构体数组,成员包括学号,姓名,四门成绩,以及平均成绩;
2、从键盘上输入学生的学号,姓名和四门成绩;
3、找出学生中考试没有通过的学生姓名并输出;找出考试在90分以上的学生并输出。
三、实验要求
1、要求用链表存储学生的记录,并设计出输入和查找的基本操作算法。
2、在实验过程中,分析算法的时间复杂度和空间复杂度进行分析。
四、实验环境
PC微机
DOS操作系统或Windows操作系统
TurboC程序集成环境或VisualC++程序集成环境
五、算法分析
创建一个学生结构体数组,其中包括指向下一个学生的指针。
用链表存储学生的记录,指针指向学生结构体数组的成员,输入数据存放在相应位置。
用p=p->next实现链表的滑动,查找链表上的相关信息。
六、实验内容和过程
1、用所选择的语言实现算法;
【程序清单】
#include
#include
#defineLENsizeof(structstu)//宏定义结构体的长度为LEN
#defineNULL0
structstu//定义一个学生结构体数组
{
longintnum;//学生学号
charname[20];//学生姓名
floatscore[4];//记录学生四门成绩的数组
floataverSocre;//平均成绩
structstu*next;//指向下一个学生的指针
};
floataver(structstust)//计算平均成绩的函数
{
floatsum=0;
inti;
for(i=0;i<4;i++)
sum=sum+st.score[i];
sum=sum/4;
return(sum);
}
structstu*creat(void)//创建学生结构体数组
{
structstu*head,*p1,*p2;//p1为当前所指学生结构体元素,p2指向新创建的p1
intn=0;
p1=p2=(structstu*)malloc(LEN);
printf("*****************************************************\n");
printf("输入学生学号:
");//先创建表首,输入第一个学生的成员值,如果第一个学生的学号为,则结束输入
scanf("%d",&p1->num);
if(p1->num==0)
return(head);
printf("输入学生姓名:
");
scanf("%s",&p1->name);
printf("输入学生成绩一:
");
scanf("%f",&p1->score[0]);
printf("输入学生成绩二:
");
scanf("%f",&p1->score[1]);
printf("输入学生成绩三:
");
scanf("%f",&p1->score[2]);
printf("输入学生成绩四:
");
scanf("%f",&p1->score[3]);
printf("*****************************************************\n");
p1->averSocre=aver(*p1);
head=NULL;
while(p1->num)
{
n=n+1;
if(n==1)
head=p1;
else
p2->next=p1;//将p1所指内容赋给p2
p2=p1;
p1=(structstu*)malloc(LEN);//继续输入学生的成员值
printf("*****************************************************\n");
printf("输入学生学号:
");
scanf("%d",&p1->num);
if(p1->num==0)
break;//如果输入的学生的学号为,则结束输入,跳出循环体
printf("输入学生姓名:
");
scanf("%s",&p1->name);
printf("输入学生成绩一:
");
scanf("%f",&p1->score[0]);
printf("输入学生成绩二:
");
scanf("%f",&p1->score[1]);
printf("输入学生成绩三:
");
scanf("%f",&p1->score[2]);
printf("输入学生成绩四:
");
scanf("%f",&p1->score[3]);
printf("*****************************************************\n");
p1->averSocre=aver(*p1);
}
p2->next=NULL;//链表表尾指空
return(head);
}
voidmain()
{
voidpass(structstu*p4);
structstu*p3;
p3=creat();//创建学生结构体
pass(p3);//成绩优秀及不及格的学生并输出学生相关信息
getchar();//等待输入,便于查看输出结果
getchar();
}
voidpass(structstu*p4)//选择成绩优秀及不及格的学生并输出学生相关信息
{
inti;
printf("*****************************************************\n");
while(p4!
=NULL)
{
for(i=0;i<4;i++)
{
if(p4->score[i]<60)
{
printf("%s【挂科】\n学号:
%ld\n成绩分别为:
%f,%f,%f,%f\n平均分:
%f\n",p4->name,p4->num,p4->score[0],p4->score[1],p4->score[2],p4->score[3],p4->averSocre);
break;
}
elseif(p4->score[i]>=90)
{
printf("%s【优秀】\n学号:
%ld\n成绩分别为:
%f,%f,%f,%f\n平均分:
%f\n",p4->name,p4->num,p4->score[0],p4->score[1],p4->score[2],p4->score[3],p4->averSocre);
break;
}
}
p4=p4->next;
}
printf("*****************************************************\n");
}
2、测试程序,并对算法进行时间和空间复杂度分析。
七、实验结果
八、总结和感想
对C语言基础练习的实验并不是老师要求做的实验,但我还是认真的做了,因为我觉得需要复习一下之前学过的C语言内容。
因为我们用的教材是C++版的数据结构,与C语言版的数据结构在描述一种数据结构上还是有区别的,C语言是用结构体而C++是用类。
通过本次实验对结构体的知识做了一定的复习和了解,也复习了课本上的知识。
一开始看到实验题目就想用以前学过的知识直接编程出来,但是才发现是要用链表来存储,这与数组存储相比还是比较困难的,查阅了很多资料终于做出来了,我觉得对我接下来的实验来说是次很好的基础。
实验2:
线性表及其应用
姓名:
学号:
专业班级:
计算机科学与技术091班
一、实验目的
帮助学生掌握线性表的基本操作在顺序和链表这两种存储结构上的实现,尤以链表的操作和应用作为重点。
二、问题描述
1.构造一个空的线性表L。
2.在线性表L的第i个元素之前插入新的元素e;
3.在线性表L中删除第i个元素,并用e返回其值。
三、实验要求
1、分别利用顺序和链表存储结构实现线性表的存储,并设计出在不同的存储结构中线性表的基本操作算法。
2、在实验过程中,对相同的操作在不同的存储结构下的时间复杂度和空间复杂度进行分析。
四、实验环境
PC微机
DOS操作系统或Windows操作系统
TurboC程序集成环境或VisualC++程序集成环境
五、算法分析
【顺序存储的核心算法描述】
插入:
顺序表的插入操作是指在线性表的第i-1个数据元素和第i个数据元素之间插入一个新的数据元素,使长度为n的线性表变成长度为n+1的线性表,数据元素ai-1和ai之间的逻辑关系发生了变化。
因此,除非i=n+1,否则必须移动元素才能反映这个逻辑上的变化。
一般情况下,在第i(1≤i≤n)个元素之前插入一个元素时,需将第n至第i(共n-i+1)个元素向后移动一个位置。
删除:
顺序表的删除操作是使长度为n的线性表变成长度为n—1的线性表,数据元素ai-1、ai和ai+1之间的逻辑关系发生了变化。
一般情况下,删除第i(1≤i≤n)个元素时需将第i+1至第n(共n-1)个元素向前移动一个位置。
【链式存储的核心算法描述】
插入:
链表的插入操作是将值为x的新结点插入到表的第i个结点的位置上,即插入到ai-1与ai之间。
具体步骤:
(1)找到ai-1存储位置p
(2)生成一个数据域为x的新结点*s
(3)令结点*p的指针域指向新结点
(4)新结点的指针域指向结点ai。
删除:
链表的删除操作是将表的第i个结点删去。
具体步骤:
(1)找到ai-1的存储位置p(因为在单链表中结点ai的存储地址是在其直接前趋结点ai-1的指针域next中。
(2)令p->next指向ai的直接后继结点(即把ai从链上摘下)
(3)释放结点ai的空间。
六、实验内容和过程
我选择的是C语言来设计实现线性表的顺序和链表存储结构,并在这两种存储结构下实现线性表的插入、删除算法。
顺序表和链表的程序代码清单如下:
【顺序表程序清单】
#include
#include
#defineElemTypechar
#defineLIST_INIT_SIZE100
#defineLISTINCREMENT10
#defineOVERFLOW0
#defineOK1
typedefstruct{
ElemType*elem;//顺序表中的元素指针
intlength;//顺序表的长度
intlistsize;//顺序表的大小
}SqList;
//顺序表的初始化功能
intInitList(SqList&L){
L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if(!
L.elem)
returnOVERFLOW;
L.length=0;
L.listsize=LIST_INIT_SIZE;
returnOK;
}
//顺序表的插入操作
intListInsert(SqList&L,inti,ElemTypee){
if(i<1||i>L.length+1)
return0;//如果越界则返回0
if(L.length>=L.listsize){
ElemType*newbase;
newbase=(ElemType*)realloc(L.elem,
(L.listsize+LISTINCREMENT)*sizeof(ElemType));
if(!
newbase)
returnOVERFLOW;
L.elem=newbase;
L.listsize+=LISTINCREMENT;
}
ElemType*q;
ElemType*p;
q=L.elem+i-1;
for(p=L.elem+L.length-1;p>=q;--p)
*(p+1)=*p;
*q=e;
++L.length;
returnOK;
}
//删除第i个结点并返回e值
intListDelete(SqList&L,inti,ElemType&e){
if((i<1)||(i>L.length))
return0;
ElemType*p;
ElemType*q;
p=&(L.elem[i-1]);
e=*p;
q=L.elem+L.length-1;
for(++p;p<=q;++p)*(p-1)=*p;
--L.length;
returnOK;
}
//输出顺序表的函数
voidPrint(SqList&L){
printf("\n****************************************\n");
printf("当前顺序表为:
\n");
printf("");
for(inti=0;iprintf("%1c",L.elem[i]);
}
printf("\n");
}
//顺序表的输入函数
voidInput(SqList&L){
intn;
ElemTypee;
InitList(L);
printf("\n****************************************\n");
printf("请输入顺序表中元素的个数:
");
scanf("%d",&n);fflush(stdin);//清空缓冲区
printf("\n请输入顺序表中的元素:
");
for(inti=0;i{
scanf("%c",&e);
ListInsert(L,i+1,e);
}
Print(L);
}
//顺序表插入操作的测试函数
voidinsert(){
SqListL;
inti;
ElemTypee;
Input(L);
printf("\n****************************************\n");
printf("请输入要插入的元素的位置:
");
scanf("%d",&i);fflush(stdin);
printf("\n");
printf("请输入要插入的元素:
");
scanf("%c",&e);fflush(stdin);
ListInsert(L,i,e);
Print(L);
}
//顺序表删除操作的测试函数
voiddeletei(){
SqListL;
inti;
ElemTypee;
Input(L);
printf("****************************************\n");
printf("请输入要删除的元素的位置:
");
scanf("%d",&i);fflush(stdin);//清空缓冲区
ListDelete(L,i,e);
Print(L);
}
voidmain(){
SqListL;
intchoose,flag;
flag=1;
while(flag){
printf("***********顺序表操作***********\n");
printf("1.在第i个元素之前插入一个元素\n");
printf("2.删除第i个元素\n");
printf("其他.结束");
printf("\n****************************************\n");
printf("");
scanf("%d",&choose);
switch(choose){
case1:
insert();
break;
case2:
deletei();
break;
default:
flag=0;
break;
}
}
getchar();
}
【链表程序清单】
//链表的初始化、插入、删除算法
#include
#include
#include
#defineElemTypechar
#defineLIST_INIT_SIZE100
#defineLISTINCREMENT10
#defineOVERFLOW0
#defineOK1
typedefstructLnode{
ElemTypedata;
structLnode*next;
}Lnode,*Linklist;//头指针
//链表初始化
intInitLinklist(Linklist&L)
L=(Linklist)malloc(sizeof(Lnode));
if(!
L)
returnOVERFLOW;
L->next=NULL;//定义指针域为空
returnOK;
}
intgetlength(Linklist&L)//获得链表中的结点数
{
inti=0;
if(!
L)
return0;
Linklistp=L->next;
while(p!
=NULL){
++i;
p=p->next;
}
returni+1;
}
//向链表中插入元素
intListInsert(Linklist&L,inti,ElemTypee)
{
//在带头节点的单链表L中第i个位置之前插入元素e
Linklistp=L;
intj=1;
if(i<1)
return0;
//寻找第i-1个节点并将P指向它
Linklists;
s=(Linklist)malloc(sizeof(Lnode));//生成新结点
s->data=e;
if(i==1)//插入L中
{
s->next=L;
L=s;
}
else{
while(p&&j{
j++;
p=p->next;
}
}
if(!
p)
return0;
s->next=p->next;
p->next=s;
returnOK;
}
//向链表中删除元素
intListDelete(Linklist&L,inti)
{
//在带头结点的单链表L中删除第i个数据元素元素
Linklistp;
p=L;intj=1;
if(!
L)
return0;
elseif(i==1){
L=p->next;
free(p);
}
else{
while(p->next&&j{//寻找第i个结点,并另p指向其前趋
p=p->next;
j++;
}
if(!
(p->next)||j>i-1)//删除位置不合理
return0;//删除并释放结点
Linklistq=p->next;
p->next=q->next;//即使是删除最后一个元素,空指针也能继承
free(q);
}
return1;
}
//显示链表的函数
voidPrint(Linklist&L){
Linklistp;
p=L;
printf("****************************************\n");
printf("当前链表为:
\n");
printf("");
intm=getlength(L);
for(inti=0;iprintf("[%d]",i+1);
printf("\n");
printf("");
while(p){
if(p->data<10)
printf("");
printf("%c->",p->data);
p=p->next;
}
printf("\n");
}
//输入链表的函数
voidInput(Linklist&L){
intn;
ElemTypee;
InitLinklist(L);
printf("****************************************\n");
printf("请输入链表中结点的个数:
");
scanf("%d",&n);fflush(stdin);//用于清空缓冲区
printf("\n请输入链表的结点:
");
for(inti=0;i{
//e=getchar();
scanf("%c",&e);
ListInsert(L,i+1,e);
}
Print(L);
}
//插入的测试函数
voidinsert(){
LinklistL;
inti,n;
ElemTypee;
Input(L);
printf("****************************************\n");
printf("请输入要插入的元素的位置:
");
scanf("%d",&i);fflush(stdin);//用于清空缓冲区
printf("\n");
printf("请输入要插入的元素:
");
//e=getchar();
scanf("%c",&e);
ListInsert(L,i,e);
Print(L);
}
//删除的测试函数
voiddeletei(){
LinklistL;
inti;
ElemTypee;
Input(L);
printf("****************************************\n");
printf("请输入要删除的元素的位置:
");
scanf("%d",&i);fflush(stdin);
//printf("\n请输入要删除的元素:
");
//scanf("%d",&e);
ListDelete(L,i);
Print(L);
}
voidmain(){
LinklistL;
inti;
ElemTypee;
in