数据结构课程上机实验教学.docx
《数据结构课程上机实验教学.docx》由会员分享,可在线阅读,更多相关《数据结构课程上机实验教学.docx(29页珍藏版)》请在冰豆网上搜索。
数据结构课程上机实验教学
数据结构实验指导
说明:
课内上机要求完成实验一到实验四的内容,并完成实验报告,实验报告在第十六周星期三之前交,其他实验请大家课外抽时间完成。
给出的示例程序供大家参考,大家实验的时候要自己动手编写程序,切不可完全照抄,每个实验具体的实验题目大家可以做示例的题目,也可以自己定一题目,只需用到该实验的知识点即可,编程语言大家可以选用自己熟悉的语言。
一.实验要求:
书写类C语言的算法,并将算法转变为程序实现。
正确理解各种数据结构的逻辑特性和存储表示和基本操作的算法实现。
针对问题的不同选择合适的数据结构,提高算法设计的能力和动手实验的技能。
二.主要仪器设备:
(所开实验的主要仪器设备)
硬件要求:
在多媒体教室讲解及演示。
为保证教学顺利进行,要求实验室提供PⅢ及以上的微机。
三.实验项目内容简介:
为了达到实验目的,本课程安排了四个实习单元,训练的重点在于基本的数据结构,而不是强调面面俱到。
各实习单元与教科书的各章只具有粗略的对应关系,一个实习题常常涉及到几部分教学内容。
1、线性表基本操作
(1) 熟悉线性表的基本运算在两种存储结构(顺序结构和链式结构)上的实现
(2)以线性表的各种操作(建立、插入、删除、求最大最小值等)的实现为重点
(3) 通过本次实习帮助学生加深对c++的使用(特别是函数参数、指针类型、链表的使用)。
2、栈、队列以及递归算法的设计
(1)掌握栈和队列这两种特殊的线性表,熟悉它们的特性,在实际问题背景下灵活运用它们
(2) 训练的要点是“栈”的观点及其典型用法;问题求解的状态表示及其递归算法;由递归程序到非递归程序的转化方法。
3、树、图及其应用
(1) 树和图是两种非线性数据结构,广义表的实质是树结构,而稀疏矩阵的十字链表存储结构也是图的一种存储结构,故本单元是本课的实习重点。
(2) 要求学生熟悉各种存储结构的特性,以及如何应用树和图结构求解具体问题。
(3) 训练的要点是:
递归算法的设计方法;表达式的求值技术;哈夫曼方法及其编译码技术;完整的应用系统的用户界面设计和操作定义方法;矩阵乘法的特殊操作顺序;路径遍历(树、图的遍历)技术。
4、查找和排序
本次实习旨在集中对几个专门的问题做较为深入的探讨和理解
重点在掌握各种内部排序算法、查找算法的思想和实现。
学生在实习中体会查找和内部排序算法思想,理解开发高效算法的可能性和寻找、构造高效算法的方法。
四、主要参考书:
1、《数据结构题集》(C语言版)实习题部分,清华大学出版社,1999.11
2、《数据结构习题与解析》(C++语言篇),李春葆编著,清华大学出版社
3、宁正元《数据结构习题解析与上机实验指导》水利水电出版社(2003年)
实验一线性表的操作
一、实验目的
1.熟悉C++语言的上机环境,掌握C++语言的基本结构。
2.会定义线性表的顺序存储结构。
(链式存储结构)
3.熟悉对顺序表(单链表)的一些基本操作。
二、实验要求
1.认真阅读和掌握本实验内容所给的全部程序。
2.保存和打印出程序运行结果,并结合程序进行分析。
注意事项:
在做第一次“数据结构”课程实验之前,要在硬盘上建立好自己的工作目录,专门来存储你所做的实验程序及相关信息,以后每次做实验都采用这个目录。
三、实验内容
1、示例(以顺序表为示例,同学们也可以编程实现单链表的创建、查找、插入、删除、求最大最小值等功能)
以输入整形数据为主,输入后按“?
”结束输入。
程序所能表达到的功能为:
实现顺序表的创建、查找、插入、删除等功能。
程序运行后,输入数据并执行。
源程序:
#include"stdio.h"
#include"conio.h"
#defineMaxSize50
typedefcharelemtype;
typedefstructnode
{
elemtypedata[MaxSize];
intlen;
}lnode,*List;
voidinit(ListL){L->len=0;}
intlength(ListL)
{returnL->len;}
elemtypegetnode(ListL,intpos)
{
if(pos<1||pos>L->len)printf("error");
elsereturnL->data[pos-1];
}
intlocate(ListL,elemtypex)
{ inti=0;
while(ilen&&L->data[i]!
=x)i++;
if(i==L->len)return-1;
elsereturn(i+1);
}
voidinsert(ListL,intpos,elemtypex)
{ intj;
if(pos<1||pos>L->len+1)printf("inserterror\n");
else{
L->len++;
for(j=L->len;j>=pos;j--) L->data[j]=L->data[j-1];
L->data[pos-1]=x;};
}
voiddelnode(ListL,intpos)
{intj;
if(pos<1||pos>L->len)printf("delerror\n");
else{
for(j=pos;jlen;j++)
L->data[j-1]=L->data[j];
L->len--;}
}
voidprint(ListL)
{ inti;
for(i=1;ilen;i++)
printf("%c->",L->data[i-1]);
printf("%c",L->data[L->len-1]);
}
voidmain()
{
inti=1,n;
lnodeL;
charch,x;
init(&L);
printf("\n\n\n*******************************顺序表演示程序***********\n");
printf("请输入你想建立的顺序表的元素,以?
结束:
");
ch=getchar();
while(ch!
='?
')
{insert(&L,i,ch);
i++;
ch=getchar();
};
printf("你建立的顺序表为:
");
print(&L);
printf("\n顺序表的长度为:
%d",L.len);
printf("\n输入你想查找的元素:
");
fflush(stdin);
scanf("%c",&x);
printf("你查找的元素为%c序位为%d",x,locate(&L,x));
printf("\n输入你想查找的元素序位:
");
scanf("%d",&n);
printf("\n你查找的元素为:
%c",getnode(&L,n));
printf("\n输入你想插入的元素以及序位:
<用逗号隔开>");
fflush(stdin);
scanf("%c,%d",&x,&n);
insert(&L,n,x);
printf("\n插入后顺序表为:
");
print(&L);
fflush(stdin);
printf("\n请输入你想删除的元素序位:
");
scanf("%d",&n);
delnode(&L,n);
printf("\n删除后的顺序表为:
");
print(&L);
getch();
}
四、测试结果
运行程序,屏幕显示:
“请输入你想建立的顺序表的元素,以?
结束:
”
输入:
54381
你建立的顺序表为:
5—>4—>3—>8—>1
顺序表的长度为:
5
输入你想查找的元素:
4
你查找的元素为4序位为2
输入你想查找的元素序位:
4
你查找的元素为:
8
输入你想插入的元素以及序位:
<用逗号隔开>":
6,3
插入后顺序表为:
5—>4—>6—>3—>8—>1
请输入你想删除的元素序位:
5
删除后的顺序表为:
5—>4—>6—>3—>1
实验二二叉树的操作
一.实验目的
理解并熟悉掌握创建二叉树和实现二叉树的三种遍历
二.实验内容
创建二叉树和实现二叉树的三种遍历
根据提示输入字符型数据创建二叉树,输入值为所有字符型数据
输出为遍历后的每个结点的值的顺序
创建二叉树并能实现二叉树的先序、中序、后序遍历
如果输入数据为:
abc
输出结果为:
abc
bac
bca
程序流程:
main()clrscr()createtree()preorder()inorder()postorder
源程序:
#include"stdlib.h"/*引入头文件*/
structtnode/*定义二叉树存储结构*/
{chardata;
structtnode*lchild;
structtnode*rchild;
};
structtnodetree;/*定义二叉树指针*/
voidcreatetree(structtnode*t)/*创建函数*/
{structtnode*p=t;/*把二叉树指针给p*/
charcheck;
if(p->lchild==NULL||p->rchild==NULL)/*判断左右子树是否为空*/
{printf("pleaseenterthedata:
");/*输入根结点数据*/
scanf("%c",&(p->data));
getchar();
}
if(p->lchild==NULL)
{printf("%cleftchildisnull.Add?
y/n\n",p->data);/*左子树空,询问是否创建*/
scanf("%c",&check);
getchar();
if(check=='y')
{structtnode*q=(structtnode*)malloc(sizeof(structtnode));/*开辟空间*/
q->lchild=NULL;
q->rchild=NULL;
p->lchild=q;
createtree(q);
}
}
if(p->rchild==NULL)
{printf("%crightchildisNULL.Add?
y/n\n",p->data);/*右子树空,询问是否创建*/
scanf("%c",&check);
getchar();
if(check=='y')
{structtnode*q=(structtnode*)malloc(sizeof(structtnode));/*开辟空间*/
q->lchild=NULL;
q->rchild=NULL;
p->rchild=q;/*连到二叉树上*/
createtree(q);
}
}
}
voidpreorder(structtnode*t)/*先序遍历函数*/
{if(t)
{printf("%c",t->data);/*输出根结点数据*/
preorder(t->lchild);
preorder(t->rchild);
}
}
voidinorder(structtnode*t)/*中序遍历函数*/
{if(t)
{inorder(t->lchild);
printf("%c",t->data);
inorder(t->rchild);
}
}
voidpostorder(structtnode*t)/*后序遍历函数*/
{if(t)
{
postorder(t->lchild);
postorder(t->rchild);
printf("%c",t->data);
}
}
voidmain()
{
clrscr();/*清屏函数*/
tree.lchild=NULL;/*左子树*/
tree.rchild=NULL;/*右子树*/
createtree(&tree);/*创建二叉树*/
preorder(&tree);/*先序遍历*/
printf("\n");
inorder(&tree);/*中序遍历*/
printf("\n");
postorder(&tree);/*后序遍历*/
}
三.使用说明
程序运行:
先输入根结点数据,例如:
a
输入y或n判断是否创建左子树。
输入y然后输入左子树数据
输入y或n判断是否创建右子树。
输入y然后输入右子树数据
按回车可查看遍历结果并退出程序。
四.测试结果
运行程序,屏幕提示:
pleaseenterthedata:
a/*首先输入根结点,为a*/
aleftchildisnull.add?
y/n/*询问是否输入a结点的左结点*/
y/*输入*/
pleaseenterthedata:
b/*输入结点a的左结点,为b*/
bleftchildisnull.add?
y/n/*询问是否输入b结点的左结点*/
n/*不输入*/
brightchildisnull.add?
y/n/*询问是否输入b结点的右结点*/
n/*不输入*/
arightchildisnull.add?
y/n/*询问是否输入a结点的右结点*/
y/*输入*/
pleaseenterthedata:
c/*输入结点a的右结点,为c*/
cleftchildisnull.add?
y/n/*询问是否输入c结点的左结点*/
n/*不输入*/
crightchildisnull.add?
y/n/*询问是否输入c结点的右结点*/
n/*不输入*/
程序退出,显示结果应为:
abc/*先序*/
bac/*中序*/
bca/*后序*/
实验三图的遍历操作
一.实验目的:
该实验主要完成对图的创建,并实现图的深度优先遍历和广度优先遍历
二.实验内容:
所输入的数据要为整形数据
输出的形式为:
每按一次回车,遍历一个结点
能创建最大结点树为30的任意图,实现对无向图的两种遍历
程序流程:
main()clrscr()visited()DFS()visited()BFS()
源程序:
#include/*引用两个头文件*/
#definemaxvex30/*定义MAXVEX=30*/
structedgenode/*定义边的结构体*/
{intadjvex;
charinfo;
structedgenode*next;
};
structvexnode/*定义点的结构体*/
{chardata;
structedgenode*link;
};
typedefstructvexnodeadjlist[maxvex];/*自定义adjlist为结构体数组类型*/
adjlisttu1;/*定义结构体数组变量tu1*/
voidcreategraph(adjlistg,intn)/*图创建函数*/
{inte,i,s,d;/*定义存储边、点的变量*/
structedgenode*p,*q;/*定义边的结构体指针*/
printf("thepoint(n)andedge(e):
");/*显示提示输入点,边*/
scanf("%d,%d",&n,&e);/*接收点、边存入n,e中*/
for(i=1;i<=n;i++)
{getchar();
printf("\tthe%dinformation:
",i);/*提示输入结点信息*/
scanf("%c",&g[i].data);/*存储信息*/
g[i].link=NULL;/*最后指针为空*/
}
for(i=1;i<=e;i++)
{printf("\nthe%dedges=>\n\t:
",i);/*提示输入边信息*/
scanf("%d,%d",&s,&d);/*接收边的信息*/
p=(structedgenode*)malloc(sizeof(structedgenode));
q=(structedgenode*)malloc(sizeof(structedgenode));/*开辟两个存储边的空间*/
p->adjvex=d;/*把其中一个点存储下来*/
p->info=g[d].data;
q->adjvex=s;/*把另一个点存储下来*/
q->info=g[s].data;
p->next=g[s].link;/*p和s的link指针连接起来*/
g[s].link=p;
q->next=g[d].link;/*q和s的link指针连接起来*/
g[d].link=q;/*完成一个边的创建*/
}
}
intvisited[maxvex];/*定义访问数组*/
voiddfs(adjlistadj,intv)/*深度优先遍历函数*/
{inti;
structedgenode*p;/*定义边指针*/
visited[v]=1;/*把开始遍历的点在访问数组中标识*/
printf("nowisatpoint%d",v);/*输出正访问的点*/
p=adj[v].link;
printf("thedatais%c\n",adj[v].data);/*输出点的信息*/
getch();
while(p)
{if(visited[p->adjvex]==0)
dfs(adj,p->adjvex);/*没有访问的再调用DFS函数*/
p=p->next;/*访问过的判断下一个*/
}
}
intquene[maxvex];
voidbfs(adjlistadj,intvi)/*广度优先遍历函数*/
{intm=maxvex;/*定义一个队列*/
intfront=0,rear=1,v;
structedgenode*p;/*定义边指针*/
visited[vi]=1;/*开始访问的点标识一下*/
printf("nowvisitthepoint:
%d\n",vi);/*输出正访问的点*/
getch();quene[rear]=vi;/*把访问过的点放入数组中*/
while(front!
=rear)
{front=(front+1)%m;
v=quene[front];
p=adj[v].link;
while(p)
{if(visited[p->adjvex]==0)/*判断p->adjvex点是否访问过*/
{visited[p->adjvex]=1;/*访问没有访问过的结点*/
printf("nowvisitthepoint:
%d\n",p->adjvex);/*输出正访问的结点*/
getch();
rear=(rear+1)%m;
quene[rear]=p->adjvex;/*放入数组中*/
}
p=p->next;/*指向下一个*/
}
}
}
voidmain()
{inti;clrscr();
creategraph(tu1,0);/*创建图*/
for(i=1;ivisited[i]=0;/*访问数组初始化*/
dfs(tu1,1);/*调用DFS*/
getch();/*等待输入*/
for(i=1;ivisited[i]=0;
bfs(tu1,1);/*调用BFS*/
}
三.使用说明:
根据屏幕上的英文提示先输入结点的个数和边数。
然后输入各结点存储的信息,再输入定义的边,形成图。
最后分别按照DFS深度优先遍历和BFS广度优先遍历实现对图的遍历。
四.测试结果:
运行程序,屏幕提示:
thepoint(n)andedge(e):
4,3/*输入顶点和边的数目*/
the1information:
a/*各个顶点的信息*/
the2information:
b
the3information:
c
the4information:
d
the1edges=>/*各个边的连接情况*/
:
1,2
the2edges=>
:
1,3
the3edges=>
:
3,4
nowisatpoint1thedataisa/*深度优先遍历结果*/
nowisatpoint3thedataisc
nowisatpoint4thedataisd
nowisatpoint2thedataisb
nowvisitthepoint:
1/*广度优先遍历结果*/
nowvisitthepoint:
3
nowvisitthepoint:
2
nowvisitthepoint:
4
实验四栈的基本操作
一、实验目的:
1.熟练掌握栈的结构,以及这种数据结构的特点;
2.能够在两种存储结构上实现栈的基本运算,特别注意栈满和栈空的判断条件及描述方法;
二、实验内容:
计算表达式的值
【问题描述】
计算用运算符后缀法表示的表达式的值。
后缀表达式也称逆波兰表达式,比中缀表达式计算起来更方便简单些,中缀表达式要计算就存在着括号的匹配问题,所以在计算表达式值时一般都是先转换成后缀表达式,再用后缀法计算表达式的值。
如:
表达式(a+b*c)/d-e用后缀法表示应为abc*+d/e-。
只考虑四则算术运算,且假设输入的操作数均为1位十进制数(0—9),并且输入的后缀形式表达式不含语法错误。
【数据描述】
#defineadd43/*运算符加号‘+’的ASCII码*/
#definesubs