数据结构实验五实验报告.docx
《数据结构实验五实验报告.docx》由会员分享,可在线阅读,更多相关《数据结构实验五实验报告.docx(14页珍藏版)》请在冰豆网上搜索。
数据结构实验五实验报告
数据结构实验报告
实验五
图子系统
实验题目:
图的遍历问题
专业班级:
网络工程1002班
组长:
王星(30)
组员:
郭坤铭(43)
张磊(44)
2012年5月18日
实验报告
实验类型__综合__实验室_软件实验室二__
一、实验题目
图的遍历问题
二、实验目的和要求
1、掌握图的存储思想及其存储实现
2、掌握图的深度、广度优先遍历算法思想及其程序实现
3、掌握图的常见应用算法的思想及其程序实现
三、需求分析
本演示程序用c++6.0编写,完成用户用键盘输入以下结点数据:
太原、成都、北京、上海、天津、大连、河北。
(1)建立一个有向图或无向图(自定)的邻接表并输出该邻接表。
(2)在图的邻接表的基础上计算各顶点的度,并输出。
(3)以有向图的邻接表为基础实现输出它的拓扑排序序列。
(4)采用邻接表存储实现无向图的深度优先遍历。
(5)采用邻接表存储实现无向图的广度优先遍历。
(6)采用邻接矩阵存储实现无向图的最小生成树的PRIM算法。
最后,在主函数中设计一个简单的菜单,分别调试上述算法。
四、概要设计
为了实现上述程序功能,需要定义如下内容
基本数据类型定义如下:
typedefstructnode{//边表结点
intadj;//边表结点数据域
structnode*next;
}node;
typedefstructvnode//顶点表结点
{charname[20];
node*fnext;
}vnode,AList[20];
typedefstruct
{AListList;//邻接表
intv,e;//顶点树和边数
}*Graph;
GraphCreatDG(){}//建立无向邻接表
GraphCreatAG(){} //有向邻接图
voidPrint(GraphG){}//输出图的邻接表
voidCreateAN(AGraph*G1){}//构造邻接矩阵结构的图G
voidDu(GraphG){}//输出各顶点的度数
voidDFSTravel(GraphG){}//深度优先遍历
voidBFSTravel(GraphG){}//广度优先遍历
五、详细设计
#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;iv;i++){
printf("请输入图中第%d元素:
",i+1);
scanf("%s",G->List[i].name);//读入顶点信息
G->List[i].fnext=NULL;//边表置为空表
}
for(k=0;ke;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;iv;i++){
printf("请输入图中第%d元素:
",i+1);
scanf("%s",&G->List[i].name);//读入顶点信息
G->List[i].fnext=NULL;
}
for(k=0;ke;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;iv;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;iv;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;iv;i++){
p=G->List[i].fnext;;
while(p!
=NULL){
indegree[p->adj]++;
p=p->next;
}
}
for(i=0;iv;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(countv)printf("有回路!
");
}
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;iv;i++)
flag[i]=0;
for(i=0;iv;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;iv;i++)
flag[i]=0;
for(i=0;iv;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].lowcostw=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;iv1;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、程序名为实验5.exe,运行坏境为DOS.程序执行后显示如图所示:
2、建立无向邻接图
3、输出各顶点的度
4、进行深度优先遍历
5、进行广度优先遍历
6、建立有向邻接图
7、拓扑排序
8、建立无向邻接矩阵
9、prim算法生成最小生成树
七、实验总结
本次实验对我们来说有不小的难度,花费了很长的时间,在大家的商量讨论和共同努力下,最终完成了实验的内容,组长在此过程中很认真负责,使组员一步一步前进。
同时,这使我们在图这方面的知识更加全面,通过实验进一步增强了我们的实际运用知识的能力,对我们很有帮助。