数据结构实验报告图的遍历讲解.docx
- 文档编号:5847494
- 上传时间:2023-01-01
- 格式:DOCX
- 页数:19
- 大小:211.97KB
数据结构实验报告图的遍历讲解.docx
《数据结构实验报告图的遍历讲解.docx》由会员分享,可在线阅读,更多相关《数据结构实验报告图的遍历讲解.docx(19页珍藏版)》请在冰豆网上搜索。
数据结构实验报告图的遍历讲解
数据结构试验报告
实验四
图的存储及应用
实验题目:
图的遍历问题
专业班级:
计科系1405班
组长:
张纪远(2014100518)
组员:
周振军(2014100551)
朱新祥(2014100552)
梁丽蓉(2014100526)
段慧娟(2014100512)
2016年6月1日
实验报告
实验类型__综合设计__实验室_软件实验室三__
一、实验题目
图的存储及应用
二、实验目的和要求
1.掌握图的存储思想及其存储实现
2.掌握图的深度、广度优先遍历算法思想及其程序实现
3.掌握图的常见应用算法的思想及其程序实现
三、需求分析
1.问题描述
使用菜单实现图的相关算法,如键盘输入以下结点数据:
太原、成都、北京、上海、天津、大连、河北,建立一个有向图或无向图(自定)的邻接表并输出该邻接表;在图的邻接表的基础上计算各顶点的度,并输出;以有向图的邻接表为基础实现输出它的拓扑排序序列;采用邻接表存储实现无向图的深度优先遍历;采用邻接表存储实现无向图的广度优先遍历;采用邻接矩阵存储实现无向图的最小生成树的PRIM算法
2.设计分析
调用菜单项,分别调用相应的子函数。
注意顶点存储地名,使用字符数组来实现。
3.结构类型定义
typedefcharvextype[10];/*顶点数据类型*/
typedefintedgetype;/*边数据类型*/
typedefstruct{
vextypevex[MAXSIZE];
edgetypearc[MAXSIZE][MAXSIZE];
intvexnum,arcnum;
}Mgraph;
typedefstructnode{
intadjvex;
structnode*next}EdgeNode;
typedefstructnode{
vextypevex;
EdgeNode*firstedge;}VexNode;
typedefstruct{
VexNodeadjvex[MAXSIZE];
intn,e;}ALGraph;
四、概要设计
为了实现上述程序功能,代码如下:
#include
#include
#include
typedefstructnode{//边表结点
intadj;//边表结点数据域
structnode*next;
}node;
typedefstructvnode{//顶点表结点
charname[20];
node*fnext;
}vnode,AList[20];
typedefstruct{
AListList;//邻接表
intv,e;//顶点树和边数
}*Graph;
//建立无向邻接表
GraphCreatDG(){
GraphG;
inti,j,k;
node*s;
G=malloc(20*sizeof(vnode));
printf("请输入图的顶点数和边数(空格隔开):
");
scanf("%d%d",&G->v,&G->e);//读入顶点数和边数
for(i=0;i
printf("请输入图中第%d元素:
",i+1);
scanf("%s",G->List[i].name);//读入顶点信息
G->List[i].fnext=NULL;//边表置为空表
}
for(k=0;k
printf("请请输入第%d条边的两顶点序号(空格隔开):
",k+1);
scanf("%d%d",&i,&j);//读入边(Vi,Vj)的顶点对序号;
s=(node*)malloc(sizeof(node));//生成边表结点
s->adj=j;
s->next=G->List[i].fnext;
G->List[i].fnext=s;//将新结点*s插入顶点Vi的边表头部
s=(node*)malloc(sizeof(node));
s->adj=i;//邻接点序号为i
s->next=G->List[j].fnext;
G->List[j].fnext=s;//将新结点*s插入顶点Vj的边表头部
}
returnG;
}
//有向邻接图
GraphCreatAG(){
GraphG;
inti,j,k;
node*q;
G=malloc(20*sizeof(vnode));
printf("请输入图的顶点数和边数【空格隔开】:
");
scanf("%d%d",&G->v,&G->e);
for(i=0;i
printf("请输入图中第%d元素:
",i+1);
scanf("%s",&G->List[i].name);//读入顶点信息
G->List[i].fnext=NULL;
}
for(k=0;k
printf("请请输入第%d边的两顶点序号【空格隔开】:
",k+1);
scanf("%d%d",&i,&j);
q=(node*)malloc(sizeof(node));//生成新边表结点s
q->adj=j;//邻接点序号为j
q->next=G->List[i].fnext;
G->List[i].fnext=q;
}
returnG;
}
//输出图的邻接表
voidPrint(GraphG){
inti;
node*p;
printf("\t=======邻接表========\n");
for(i=0;i
p=G->List[i].fnext;
printf("%d|%3s",i,G->List[i].name);
while(p){
printf("->%3s",G->List[p->adj].name);
printf("->%d",p->adj);
p=p->next;
}
printf("\n");
}
}
typedefstruct{
charvex[20];
}Lists[20];
typedefstruct{
Listsl;
intedge[20][20];//邻接矩阵
intv1,e1;//顶点数和弧数
}AGraph;
typedefstruct{
intdata;/*某顶点与已构造好的部分生成树的顶点之间权值最小的顶点*/
intlowcost;/*某顶点与已构造好的部分生成树的顶点之间的最小权值*/
}ClosEdge[20];/*用普里姆算法求最小生成树时的辅助数组*/
voidCreateAN(AGraph*G1){
/*构造邻接矩阵结构的图G*/
inti,j,k,w;
printf("请输入图的顶点数和边数(空格隔开):
");
scanf("%d%d",&G1->v1,&G1->e1);//读入顶点数和边数
for(i=1;i<=G1->v1;i++){
printf("请输入图%d号元素:
",i);
scanf("%s",&G1->l[i].vex);//读入顶点信息
}
for(i=1;i<=G1->v1;i++)//初始化邻接矩阵
for(j=1;j<=G1->v1;j++)
G1->edge[i][j]=9;
for(k=1;k<=G1->e1;k++){
printf("请输入两顶点及边的权值(空格隔开):
");
scanf("%d%d%d",&i,&j,&w);
G1->edge[i][j]=w;
G1->edge[j][i]=w;
}
}
voidPrintAN(AGraph*G1){
inti,j;
printf("\t=======邻接矩阵========\n");
for(i=1;i<=G1->v1;i++){
for(j=1;j<=G1->v1;j++)
printf("%3d",G1->edge[i][j]);
printf("\n");
}
}
//输出各顶点的度数
voidDu(GraphG){
inti,j;
node*p;
printf("\n<----各点度数---->\n");
for(i=0;i
p=G->List[i].fnext;
printf("顶点%2s的度为:
",G->List[i].name);
j=0;
while(p){
j++;
p=p->next;
}
printf("%d\n",j);
}
}
//栈
typedefstructstack{
intx;
structstack*next;
}stack;
intpush(stack*s,inti){
stack*p;
p=(stack*)malloc(sizeof(stack));
p->x=i;
p->next=s->next;
s->next=p;
return1;
}
intpop(stack*s,intj){
stack*p=s->next;//保存栈顶指针
j=p->x;
s->next=p->next;//将栈顶元素摘下
free(p);//释放栈顶空间
returnj;
}
//拓扑排序
voidTopo(GraphG,stack*s){
inti,k,count;
intj=0;
intindegree[20]={0};
node*p;
for(i=0;i
p=G->List[i].fnext;;
while(p!
=NULL){
indegree[p->adj]++;
p=p->next;
}
}
for(i=0;i
if(indegree[i]==0)
push(s,i);
count=0;
while(s->next!
=NULL){
i=pop(s,j);
printf("%2s",G->List[i].name);
++count;
for(p=G->List[i].fnext;p!
=NULL;p=p->next){
k=p->adj;
if(!
(--indegree[k]))
push(s,k);
}
}
if(count
");
}
voidDFS(GraphG,inti,intflag[]){
node*p;
printf("%2s",G->List[i].name);
flag[i]=1;
p=G->List[i].fnext;
while(p){
if(!
flag[p->adj])
DFS(G,p->adj,flag);
p=p->next;
}
}
//深度优先遍历
voidDFSTravel(GraphG){
inti;
intflag[20];//标志数组
for(i=0;i
flag[i]=0;
for(i=0;i
if(!
flag[i])
DFS(G,i,flag);
}
//建立队列
typedefstruct{
int*elem;
intfront,rear;
}*Queue;
//队列初始化
voidInitQueue(QueueQ){
Q->elem=(int*)malloc(20*sizeof(int));
if(!
Q->elem)
exit(0);
Q->front=Q->rear=0;
}
//入队
voidEnter(QueueQ,inte){
if((Q->rear+1)%20!
=Q->front)
Q->elem[Q->rear]=e;
else
printf("队列满!
\n");
Q->rear=(Q->rear+1)%20;
}
//出队
voidLeave(QueueQ,inte){
if(Q->rear!
=Q->front)
e=Q->elem[Q->front];
else
printf("队列空!
\n");
Q->front=(Q->front+1)%20;
}
//广度优先遍历
voidBFSTravel(GraphG){
QueueQ;
node*p;
inti,j=0;
intflag[20];//标志数组
Q=malloc(sizeof(20));
InitQueue(Q);
for(i=0;i
flag[i]=0;
for(i=0;i
if(flag[i]==0){
flag[i]=1;
printf("%2s",G->List[i].name);
Enter(Q,i);
while(Q->front!
=Q->rear){
Leave(Q,j);//队头元素出队并置为j
p=G->List[j].fnext;
while(p!
=NULL){
if(flag[p->adj]==0){
printf("%2s",G->List[p->adj].name);
flag[p->adj]=1;
Enter(Q,p->adj);
}
p=p->next;
}
}
}
}
intminimum(ClosEdgecl,intvnum){
inti;
intw,p;
w=1000;
for(i=1;i<=vnum;i++)
if(cl[i].lowcost!
=0&&cl[i].lowcost w=cl[i].lowcost;p=i; } returnp; } voidPrim(AGraph*G1,intu){ ClosEdgeclosedge; inti,j,k; for(j=1;j<=G1->v1;j++)/*辅助数组初始化*/ if(j! =u){ closedge[j].data=u; closedge[j].lowcost=G1->edge[u][j]; } closedge[u].lowcost=0;/*初始,U={u}*/ for(i=1;i k=minimum(closedge,G1->v1);/*求出生成树的下一个顶点*/ printf("%d-----%d\n",closedge[k].data,k);/*输出生成树的边*/ closedge[k].lowcost=0;/*第k顶点并入U集*/ for(j=1;j<=G1->v1;j++)/*新顶点并入U后,修改辅助数组*/ if(G1->edge[k][j] closedge[j].data=k; closedge[j].lowcost=G1->edge[k][j]; } } } //菜单列表 voidmenu(){ printf("\t**********************图的遍历问题**********************\n"); printf("\t\t-------1.建立无向邻接图---------\n"); printf("\t\t-------2.建立有向邻接图---------\n"); printf("\t\t-------3.建立无向邻接矩阵---------\n"); printf("\t\t-------4.输出各顶点的度---------\n"); printf("\t\t-------5.拓扑排序---------\n"); printf("\t\t-------6.深度优先遍历---------\n"); printf("\t\t-------7.广度优先遍历---------\n"); printf("\t\t-------8.prim算法生成最小生成树---------\n"); printf("\t\t-------9-退出---------\n"); printf("\t********************************************************\n"); } //主函数 voidmain(){ GraphG; AGraphG1; intchoice,u; stack*s=(stack*)malloc(sizeof(stack)); s->next=NULL; while (1){ menu(); printf("请输入选择: "); scanf("%d",&choice); switch(choice) { case1: G=CreatDG();Print(G);printf("\n\n");break; case2: G=CreatAG();Print(G);printf("\n\n");break; case3: CreateAN(&G1);PrintAN(&G1);printf("\n\n");break; case4: Du(G);printf("\n\n");break; case5: printf("拓扑排序: ");Topo(G,s);printf("\n\n");break; case6: printf("深度优先遍历: ");DFSTravel(G);printf("\n\n");break; case7: printf("广度优先遍历: ");BFSTravel(G);printf("\n\n");break; case8: printf("请输入起点序号: "); scanf("%d",&u); printf("Prim算法: \n"); Prim(&G1,u);printf("\n"); break; case9: exit(0); default: printf("输入错误,请重新输入: \n\n"); } } } 五、使用说明 1、程序名为实验图的遍历.exe,运行坏境为VC6.0.程序执行后显示如图所示: 2、建立无向邻接图 3、输出各顶点的度 4、进行深度优先遍历 5、进行广度优先遍历 6、建立有向邻接图 7、拓扑排序 8、建立无向邻接矩阵 9、prim算法生成最小生成树 八、实验总结 通过对本次试验的学习,使我们明白了合作分工的重要性,这并不是一个容易的过程,中间碰到了许多问题,但我们都一一解决,有关于图这部分的内容很复杂,但是却非常重要,掌握好图的遍历有助于我们提升今后解决实际问题的能力,对我们非常有帮助。 注: 模块分工 张纪远(2014100518)主函数的编写及页面的设计; 段慧娟(2014100512)建立无向连接图及有向连接图; 梁丽蓉(2014100526)建立无向邻接矩阵及及输出各顶点的度; 周振军(2014100551)拓扑排序及深度优先遍历; 朱新祥(2014100552)广度优先遍历及prim算法生成最小生成树。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 实验 报告 遍历 讲解