实验.docx
《实验.docx》由会员分享,可在线阅读,更多相关《实验.docx(54页珍藏版)》请在冰豆网上搜索。
实验
连洁
工商管理学院
2010年7月
目录
第一部分数据结构课程实验概述3
一.实验目的3
二.实验要求3
2.1实验步骤3
2.2考核及评分办法5
三、验证算法的方法5
3.1类C语言与标准C的转换要点5
3.2验证算法的源程序结构9
3.3验证算法的源程序举例10
第二部分上机实验内容14
实验一C语言复习及初步认识14
实验二线性表16
实验三栈和队列29
实验四串39
实验五数组和广义表46
实验六树56
实验七图63
实验八查找70
实验九排序73
第一部分数据结构课程实验概述
一.实验目的
上机实验是对学生的一种全面综合训练,是与课堂听课、自学和练习相辅相成的必不可少的一个教学环节。
实验目的着眼于原理与应用的结合,使学生学会如何把书上的知识用语解决实际问题,能够理解和运用常用的数据结构,如线性表、栈、队列、树、图、查找表等,并在此基础上建立相应的算法;通过上机实验使学生了解算法和程序的区别,培养学生把算法转换为程序的能力,提高学生解决实际问题的能力;学会分析研究计算机加工的数据结构的特性,以便为应用涉及的数据选择适当的逻辑结构、存储结构及其相应的算法,并初步掌握算法的时间分析和空间分析的技术。
加*号的题目可以选做。
二.实验要求
2.1实验步骤
设计步骤的规范不但可以培养学生科学的工作方法和作风,而且还能有效地减少错误,提高工作效率。
因此必须严格执行良好的实验步骤规范(包括上机操作规范)。
本课程实验的基本步骤是:
2.1.1问题分析
充分地分析和理解问题本身,明确问题要求做什幺。
对问题的描述应避开算法和所涉及的数据类型,而是对所需完成的任务作出明确的回答。
例如;输入、输出数据的类型、值的范围以及形式等。
同时为调试程序准备好测试数据,包含合法的输入数据和非法形式输入的数据。
2.1.2设计和编码
设计即是对问题描述中涉及的操作对象定义相应的数据类型,定义主程序模块和各抽象数据类型;定义相应的存储结构并写出各过程和函数的伪码算法。
在这个过程中,要综合考虑系统功能,使得系统结构清晰、合理、简单和易于调试。
编码即把详细设计的结果进一步求精为程序设计语言程序,写出源程序。
对程序中的疑问应作出记号,以便上机时注意解决。
每个明确的功能模块程序一般不超过60行,程序的每一行不得超过60个字符,否则要进一步划分。
2.1.3上机前程序静态检查
上机前程序静态检查可有效提高调试效率,减少上机调试程序时的无谓错误。
静态检查主要有两种途径:
用一组测试数据手工执行程序;通过阅读或给别人讲解自己的程序而深入全面地理解程序逻辑。
把程序中的明显错误事先排除。
2.1.4上机调试程序
上机实验时要带上《C语言》教材、《数据结构》教材、《数据结构上机实验指导书》,调试最好分模块进行,自底向下,即先调试低层过程或函数。
调试过程中应多动手确定疑点,通过修改程序来证明。
调试正确后,认真整理源程序及其注释,写出或打印出带有完整注释的且格式良好的源程序清单和结果。
2.2考核及评分办法
上机实验成绩根据上机考勤、调试情况评分,分为五级制:
优、良、中、及格、不及格,占总成绩的10%。
三、验证算法的方法
数据结构教材上的算法都是用类C语言来描述,但要验证算法只能用标准C来验证,所以存在类C语言与标准C的转换及验证算法的源程序编写问题。
3.1类C语言与标准C的转换要点
3.1.1预定义常量和类型的问题
在类C语言的算法中出现了下列常量,验证时就需在源程序中定义:
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
#defineOVERFLOW-2
#defineintStatus
3.1.2算法描述的变量问题
在类C语言算法(函数)中,辅助变量没有作变量说明,但在验证源程序的函数定义时,需对所有使用的变量(除函数参数外)作说明。
例1:
顺序表的插入算法(类C语言):
StatusListInsert_Sq(SqList&L,intpos,ElemTypee)
{
//在顺序线性表L的第pos个元素之前插入新的元素e,pos为位序
//pos的合法值为1≤pos≤Listlength_Sq(L)+1
if(pos<1||pos>L.length+1)returnERROR;
//插入位置不合法
if(L.length>=L.listsize)
{//当前存储空间已满,增加分配
newbase=(ElemType*)realloc(L.elem,
(L.listsize+LISTINCREMENT)*sizeof(ElemType));
if(!
newbase)exit(OVERFLOW);//存储分配失败
L.elem=newbase;//新基址
L.listsize+=LISTINCREMENT;//增加存储容量
}
q=&(L.elem[pos-1]);//q指示插入位置
for(p=&(L.elem[L.length-1]);p>=q;--p)*(p+1)=*p;
//插入位置及之后的元素右移
*q=e;//插入e
++L.length;//表长增1
returnOK;
}//ListInsert_Sq
验证算法源程序中算法所对应的函数定义:
intListInsert_Sq(SqList*L,intpos,ElemTypee)
{
ElemType*newbase,*p,*q;
if(pos<1||pos>L->length+1)return(-1);
if(L->length>=L->listsize)
{
newbase=(ElemType*)realloc(L->elem,(L->listsize+LISTINCREMENT)*sizeof(ElemType));
if(!
newbase)exit(-1);
L->elem=newbase;
L->listsize+=LISTINCREMENT;
}
q=&((L->elem)[pos-1]);
for(p=&((L->elem)[L->length-1]);p>=q;--p)
*(p+1)=*p;
*q=e;
++L->length;
return
(1);
}
3.1.3算法描述的参数问题
在类C语言算法(函数)中,在形参定义时,以“&”打头的参数作为引用参数,即在函数调用后发生改变的量,但在验证源程序的函数定义时,需对引用参数转换为指针类型,在函数定义内,把引用参数的使用转换为引用参数对象的使用。
例2:
顺序表的插入算法(类C语言):
StatusListInsert_Sq(SqList&L,intpos,ElemTypee)
{
//在顺序线性表L的第pos个元素之前插入新的元素e,pos为位序
//pos的合法值为1≤pos≤Listlength_Sq(L)+1
if(pos<1||pos>L.length+1)returnERROR;
//插入位置不合法
if(L.length>=L.listsize)
{//当前存储空间已满,增加分配
newbase=(ElemType*)realloc(L.elem,
(L.listsize+LISTINCREMENT)*sizeof(ElemType));
if(!
newbase)exit(OVERFLOW);//存储分配失败
L.elem=newbase;//新基址
L.listsize+=LISTINCREMENT;//增加存储容量
}
q=&(L.elem[pos-1]);//q指示插入位置
for(p=&(L.elem[L.length-1]);p>=q;--p)*(p+1)=*p;
//插入位置及之后的元素右移
*q=e;//插入e
++L.length;//表长增1
returnOK;
}//ListInsert_Sq
验证算法源程序中算法所对应的函数定义:
intListInsert_Sq(SqList*L,intpos,ElemTypee)
{
ElemType*newbase,*p,*q;
if(pos<1||pos>L->length+1)return(-1);
if(L->length>=L->listsize)
{
newbase=(ElemType*)realloc(L->elem,(L->listsize+LISTINCREMENT)*sizeof(ElemType));
if(!
newbase)exit(-1);
L->elem=newbase;
L->listsize+=LISTINCREMENT;
}
q=&((L->elem)[pos-1]);
for(p=&((L->elem)[L->length-1]);p>=q;--p)
*(p+1)=*p;
*q=e;
++L->length;
return
(1);
}
3.2验证算法的源程序结构
文件包含预处理
符号常量的定义
类型定义/*确定数据结构*/
返回类型自定义函数名(形式参数表)
/*自定义函数的定义,即算法*/
{
}
main()
{
变量定义;/*定义处理对象*/
建立对象;/*根据存储类型,给变量赋值,以确定具体的处理对象*/
调用自定义函数;/*引用函数对处理对象进行操作,实现算法的功能*/
打印输出;/*给出结果*/
}
3.3验证算法的源程序举例
例3:
顺序表的插入算法的验证方法
顺序表的插入算法:
StatusListInsert_Sq(SqList&L,intpos,ElemTypee)
{
//在顺序线性表L的第pos个元素之前插入新的元素e,pos为位序
//pos的合法值为1≤pos≤Listlength_Sq(L)+1
if(pos<1||pos>L.length+1)returnERROR;
//插入位置不合法
if(L.length>=L.listsize)
{//当前存储空间已满,增加分配
newbase=(ElemType*)realloc(L.elem,
(L.listsize+LISTINCREMENT)*sizeof(ElemType));
if(!
newbase)exit(OVERFLOW);//存储分配失败
L.elem=newbase;//新基址
L.listsize+=LISTINCREMENT;//增加存储容量
}
q=&(L.elem[pos-1]);//q指示插入位置
for(p=&(L.elem[L.length-1]);p>=q;--p)*(p+1)=*p;
//插入位置及之后的元素右移
*q=e;//插入e
++L.length;//表长增1
returnOK;
}//ListInsert_Sq
验证“顺序表的插入算法”的源程序:
//文件包含预处理
#include
#include
//符号常量的定义
#defineLIST_INIT_SIZE5
#defineLISTINCREMENT5
//类型定义(确定数据结构)
typedefintElemType;
typedefstruct{
ElemType*elem;
intlength;
intlistsize;
}SqList;
intInitList_Sq(SqList*L)
{
L->elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if(!
L->elem)exit(-1);
L->length=0;
L->listsize=LIST_INIT_SIZE;
return
(1);
}
intListInsert_Sq(SqList*L,intpos,ElemTypee)
{
ElemType*newbase,*p,*q;
if(pos<1||pos>L->length+1)return(-1);
if(L->length>=L->listsize)
{
newbase=(ElemType*)realloc(L->elem,(L->listsize+LISTINCREMENT)*sizeof(ElemType));
if(!
newbase)exit(-1);
L->elem=newbase;
L->listsize+=LISTINCREMENT;
}
q=&((L->elem)[pos-1]);
for(p=&((L->elem)[L->length-1]);p>=q;--p)
*(p+1)=*p;
*q=e;
++L->length;
return
(1);
}
voidtraverse(SqListL)
{
inti;
printf("thelistdatais:
\n");
for(i=0;iprintf("%5d",L.elem[i]);
printf("\n");
getch();
}
main()
{
inti;
SqListL;/*定义处理对象*/
InitList_Sq(&L);
/*建立对象:
根据存储类型,给变量赋值,以确定具体的处理对象*/
for(i=1;i<=10;i++)
ListInsert_Sq(&L,i,i+1);
/*调用自定义函数:
引用函数对处理对象进行操作,实现算法的功能*/
traverse(L);/*打印输出:
给出结果*/
}
第二部分上机实验内容
实验一C语言复习及初步认识
一、实验目的
本实验的目的是帮助大家复习C语言的使用方法,特别是指针、结构体的内容,同时也为以后的各个实验做准备。
二、实验内容
1、请编写函数intfun(int*a,int*b),函数的功能是判断两个指针a和b所指存储单元的值的符号是否相同;若相同函数返回1,否则返回0。
这两个存储单元中的值都不为0。
在主函数中输入2个整数、调用函数fun、输出结果。
2、计算1+2+3+……+100,要求用指针进行设计。
即设计函数intfun(int*n)实现求1+2+3+……+*n,在主函数中输入、调用、输出结果。
3、请编写函数intfun(int*a,,int*max),函数的功能是求数组a中最大数的值。
在主函数中输入10个整数、调用函数fun、输出结果。
4、请编写函数fun(int*a,intn,int*odd,int*even),函数的功能是分别求出数组a中所有奇数之和和所有偶数之和。
形参n给出数组中数据的个数;利用指针odd和even分别返回奇数之和和偶数之和。
在主函数中输入10个整数、调用函数fun、输出结果。
5、请编写函数intfun(int*a,int*b,intn),函数的功能是把数组a中所有为偶数的数,放在另一个数组中b。
在主函数中输入10个整数、调用函数fun、输出结果。
6、请编写函数intfun(int*a,,intn),函数的功能是把数组a中最大数和最小数交换。
在主函数中输入10个整数、调用函数fun、输出结果。
7、请编写函数intfun(inta[4][4]),函数的功能是把矩阵a转置。
在主函数中输入、调用函数fun、输出结果。
8、请编写函数intfun(char*a),函数的功能是分别求出字符串a的长度。
在主函数中输入1个字符串、调用函数fun、输出结果。
9、设计一个可进行复数运算的演示程序。
要求:
实现下列六种基本运算:
1)由输入的实部和虚部生成一个复数;2)两个复数求和;3)两个复数求差;4)两个复数求积;5)从已知复数中分离出实部;6)从已知复数中分离出虚部。
运算结果以相应的复数或实数的表示形式显示。
10、有5个学生,每个学生的数据包括学号、姓名、3门课的成绩,从键盘输入5个学生数据,要求打印出3门课总平均成绩,以及最高分的学生的数据。
要求:
用input函数输入5个学生数据,用average函数求总平均分;用max函数找出最高分的学生数据;总平均分和最高分学生的数据都在主函数中输出。
实验二线性表
一、实验目的
1.掌握数据结构中表的基本概念。
2.熟练掌握线性表的基本操作,插入、删除、查找,以及线性表合并等运算在顺序存储结构和链接存储结构上的实现。
3.熟练掌握链表的各种操作和应用。
二、实验内容
顺序表的基本运算的算法:
创建顺序表:
输出顺序表;插入运算;删除运算;查找运算
单链表的基本运算的算法:
创建一个单链表;输出一个单链表;求单链表的长度;查找第I个结点;插入一个结点;删除一个结点;
1、设有一个顺序表A,包含n个元素,要求写出一个将该表逆置的算法,并只允许在原表的存储空间外再增加一个附加的工作单元。
(根据题目完善源程序)
#include
#defineMaxLen50
typedefintelemtype;
structdatatype
{elemtype*elem;
intlength;
};
typedefstructdatatypesqlist;
voidcreate(sqlist*a)
{
inti,n;
a->elem=(elemtype*)malloc(MaxLen*sizeof(elemtype));
printf("创建一个顺序表\n");
printf("输入元素个数\n");
scanf("%d",&a->length);
for(i=0;ilength;i++)
{
printf("输入第%d个元素值:
",i+1);
scanf("%d",a->elem+i);
}
}
voidinvert(sqlist*a)
{
intm=a->length/2,i;
elemtypetemp;
for(i=0;i{
temp=;
*(a->elem+i)=;
=temp;
}
}
voiddisp(sqlist*a)
{inti;
for(i=0;ilength;i++)
printf("%5d:
%d\n",i+1,*(a->elem+i));
getch();
}
voidmain()
{
sqlista;
create(&a);
disp(&a);
invert(&a);
disp(&a);
}
创建一个顺序表
输入元素个数:
5
输入第1个元素值:
2
输入第2个元素值:
6
输入第3个元素值:
3
输入第4个元素值:
1
输入第5个元素值:
8
输出一个顺序表
输出一个顺序表
2、有一个单链表的第一个结点指针为head,编写一个函数将该单链表逆置,即最后一个结点变成第一个结点,原来倒数第二个结点变成第二个结点。
在逆置中不能建立新的单链表(根据题目填空完善程序)
#include
#include
#defineNULL0
typedefintelemtype;
typedefstructlinknode
{
elemtypedata;
structlinknode*next;
}nodetype;
nodetype*create()
{
elemtyped;
nodetype*h,*s,*t;
inti=1;
h=NULL;
printf("建立一个单链表\n");
while
(1)
{
printf("输入第%d节点data域值:
",i);
scanf("%d",&d);
if(d==0);/*以0表示输入结束*/
if(i==1)/*建立第一个结点*/
{
h=;
h->data=d;h->next=NULL;t=h;
}
else
{
s=(nodetype*)malloc(sizeof(nodetype));
s->data=d;s->next=NULL;t->next=s;
;/*t始终指向生成的单链表的最后一个结点*/
}
i++;
}
returnh;
}
voiddisp(nodetype*h)
{
nodetype*p=h;
printf("输出一个单链表:
\n");
if(p==NULL)printf("空表");
while(p!
=NULL)
{
printf("%d",p->data);;
}
printf("\n");
getch();
}
intlen(nodetype*h)
{
inti=0;
nodetype*p=h;
while(p)
{i++;p=p->next;}
return(i);
}
nodetype*invert(nodetype*h)
{
nodetype*p,*q,*r;
if(len(h)<=1)
{printf("逆置的单链表至少有2个节点\n");
return(NULL);
}
else
{p=h;q=p->next;
while(q!
=NULL)
{r=q->next;
q->next=p;
p=q;q=r;
}
h->next=NULL;
h=p;
returnh;
}
}
voidmain()
{
nodetype*head;
head=create();
disp(head);
head=invert();
disp(head);
}
建立一个单链表
输入第1个节点data域的值:
1
输入第2个节点data域的值:
2
输入第3个节点data域的值:
3
输入第4个节点data域的值:
4
输入第5个节点data域的值:
5
输入第6个节点data域的值:
0
输出一个单链表:
3、将两个非递减有序的单链表归并为一个非递减有序的单链表(根据题目填空完善程序)
#include“stdio.h”
#include“alloc.h”
structnode
{
chardata;
structnode*next;
}listnode;
typedefstructnode*link;