图的建立和应用.docx
- 文档编号:30708708
- 上传时间:2023-08-19
- 格式:DOCX
- 页数:65
- 大小:27.48KB
图的建立和应用.docx
《图的建立和应用.docx》由会员分享,可在线阅读,更多相关《图的建立和应用.docx(65页珍藏版)》请在冰豆网上搜索。
图的建立和应用
一、实验目的
熟悉图的存储方式,实现图的邻接矩阵或者邻接表的存储方式下的基本运算,特别是深度遍历和广度遍历;掌握以图为基础的一些常用算法,如最小生成树、拓扑排序、最短路径等
二、需求分析
1、定义图的邻接表存储结构。
2、在定义的存储结构下实现下面的操作:
(1)图的创建操作;
(2)图的销毁操作;
(3)图的深度遍历的递归算法;
(4)图的广度遍历算法;
(5)求图的最小生成树算法;
(6)求图的最短路径算法。
3、图的深度遍历算法的非递归算法;应用图的拓扑排序求关键路径的算法(选做)。
#include"stdlib.h"
#include"stdio.h"
#defineEdgeTypeint
#defineVertexTypechar
#defineMaxVerNum10
#defineMAXSIZE20
#defineDataTypeint
#defineMAX1000
#definetrue1
#definefalse0
intvisited[MaxVerNum];
//定义的一个标志图的顶点是否已经被访问的全局数组
inttag;
//用于标识图的边是否具有权值,有则tag=true,否则为false
typedefstructenode{
intadjvertex;
EdgeTypeinfo;
structenode*next;
}EdgeNode;
//定义边的信息
typedefstructvnode{
VertexTypevertex;
EdgeNode*fristEdge;
}VertexNode;
//顶点的信息
typedefstructtnode{
charvertex1,vertex2;
EdgeTypeinfo;
structtnode*next;
}*PlowestTree,lowestTree;
//prim需要的最小生成树边的数据结构
typedefstruct{
intver1,ver2;
EdgeTypeinfo;
}edgeInfo;
//kruskal法需要的数据结构
typedefstruct{
VertexNodeadjlist[MaxVerNum];
intn,e;
}ALGraph;
//定义邻接表存储的图
typedefstruct{
intdata[MAXSIZE];
intfront,rear;
}sepQueue,*PsepQueue;
//队的数据结构
typedefstruct{
DataTypedata[MAXSIZE];
inttop;
}sepStack,*PsepStack;
//栈的数据结构
typedefstructnode{
intdata;
structnode*next;
}Linkstack,*PLinkstack;
typedefstruct{
PLinkstacktop;
}stack,*Pstack;
//链栈,用于求解拓扑序列
PstackInit_stack();
/*函数功能:
初始化一个栈*/
intempty_stack(Pstacks);
//判断一个栈是否为空
intpush_stack(Pstacks,intdata);
//入栈
intpop_stack(Pstacks,int*data);
//出栈
voidDestory_stack(Pstack*s);
//销毁栈
PsepStackInit_sepStack();
//初始化一个栈
intpush_sepStack(PsepStackp,DataTypedata);
//入栈,返回0表示入栈失败,返回1表示入栈成功
intpop_sepStack(PsepStackp,DataType*data);
//出栈,返回0表示出栈失败,返回1表示出栈成功
intempty_sepStack(PsepStackp);
//判断栈是否为空,返回0表示栈空,返回1表示出栈非空
voidDestory_sepStack(PsepStack*p);
//销毁栈
PsepQueueInit_sepQueue();
//队的初始化
intempty_sepQueue(PsepQueueQ);
//判断队是否为空
intpush_sepQueue(PsepQueueQ,intdata);
//新队员入队
intpop_sepQueue(PsepQueueQ,int*data);
//队员出队
voidDestory_sepQueue(PsepQueue*Q);
//销毁队列
ALGraphcreate_undALGraph();
//创建一个无向图
voidprintf_ALGraph(ALGraphALG);
//输出采用邻接表存储的图
voiddepth_Graph(ALGraphALG);
//深度遍历图(可以计算图有几个连通分量)
voidDFS(ALGraphALG,intv);
//深度遍历图(为depth_Graph的子函数)
voidbread_Graph(ALGraphALG);
//广度遍历图(可以计算图有几个连通分量)
voidBFS(ALGraphALG,intv);
//广度遍历图(为bread_Graph的子函数)
voidcatch_values(ALGraph*ALG);
//为图中的边带权
voiduncatch_values(ALGraph*ALG);
//不为图中的边带权,即创建图时,边没有带权
voidunDepth_Graph(ALGraphALG);
//非递归法深度遍历图
voidselect_min(intlist[],int*min,intsize);
//从指定的数组中选择最小值的数组下标
PlowestTreesearch_prim_lowestTree(ALGraphALG);
//找无向带权图的最小生成树
voidprintf_lowTree(PlowestTreeTree);
//输出最小生成树的具体边组成
voidsort_edge(edgeInfoedges[],intsize);
//对边集进行按权值的升序排序
PlowestTreesearch_kruskal_lowcost(ALGraphALG);
//kruskal法寻找最小生成树
voiduncatch_Dvalues(ALGraph*DG);
//创建的有向图边不带权值
voidcatch_Dvalues(ALGraph*DG);
//创建的有向图边带有权值
ALGraphcreate_DGraph();
//创建一个有向图,函数中会询问是否给边带权值
voidselect_min(intarray[],int*min,intsize);
//从数组中选择一个最小的值,min用于存该值的下标
voidshortest_path(ALGraphG);
//求最小路径
voidprintf_vertex_shortPath(intshortPath[],ALGraphG);
//输出0到其余点的最短距离
voidcaculate_indegree(intinSum[],ALGraphDG);
//计算所有顶点的入度
inttopoOrder(ALGraphDG,inttopo[]);
//求有向图的拓扑序列
voidprintf_topo_order(ALGraphG,inttopo[]);
//输出拓扑序列
ALGraphcreate_opposite_ALGraph(ALGraphG);
//为一个邻接表图创建逆邻接表图
voidDestory_ALGraph(ALGraph*G);
//销毁一个邻接表存储的图
voidprintf_opposite_Graph(ALGraphG);
//输出逆邻接表表示的图
voidCritical_path(ALGraphG);
//AOE网的关键路径
voidprintf_event_early_later(ALGraphG,intearly[],intlater[]);
//输出事件的最早发生时间与最迟发生时间
voidcalculater_Critical_path(ALGraphG,intearly[],intlater[]);
//根据事件的最早发生时间和最迟发生时间求得关键路径
voidcalculate_event_later(ALGraphG,intlater[],inttopo[]);
//计算事件的最迟发生时间
voidcalculate_event_early(ALGraphG,intearly[],inttopo[]);
//计算事件的最早发生时间
voidDestory_lowTree(PlowestTree*tree);
//销毁最小生成树
voiddirection_graph_control();
//有向图的操作
voidun_direction_graph_control();
//无向图的操作
main()
{
inti=0;
while(i!
=3)
{
printf("**********************************\n");
printf("无向图操作菜单按1\n");
printf("有向图操作菜单按2\n");
printf("退出应用程序按3\n");
printf("**********************************\n");
printf("请选择你要进行的操作:
");
scanf("%d",&i);
switch(i)
{
case1:
un_direction_graph_control();
break;
case2:
direction_graph_control();
break;
}
if(i==3)
{
break;
}
if(i<1||i>3)
{
printf("\n你选择的操作有误,请参照以下菜单选择操作!
\n");
}
}
}
/*
*函数功能:
输出最小生成树的具体边组成
*入口参数为最小生成树
*无返回值
*/
voidprintf_lowTree(PlowestTreeTree)
{
PlowestTreep;
p=Tree->next;
printf("\n最小生成树为:
\n");
//%c----%cp->vertex1,p->vertex2
printf("边权值\n");
while(p)
{
printf("%c----%c%d\n",p->vertex1,p->vertex2,p->info);
p=p->next;
}
printf("\n");
}
/*
*函数功能:
输出以邻接表方式存储的图
*入口参数为邻接表表示的图
*无返回值
*/
voidprintf_ALGraph(ALGraphALG)
{
intk;
EdgeNode*p;
printf("\n邻接表表示的图为:
\n");
for(k=0;k { p=ALG.adjlist[k].fristEdge; if(p) { printf("%c-->",ALG.adjlist[k].vertex); } else { printf("%c",ALG.adjlist[k].vertex); } while(p) { if(p->next) { printf("%c-->",ALG.adjlist[p->adjvertex].vertex); } else { printf("%c",ALG.adjlist[p->adjvertex].vertex); } //说明: 这里输出的是顶点信息 p=p->next; } printf("\n"); } printf("\n"); } /*创建一个有向图,函数中会询问是否给边带权值*/ ALGraphcreate_DGraph() { ALGraphDG; intn,e; intk; VertexTypevt; printf("请输入要建立有向图的顶点数: "); scanf("%d",&n); printf("请输入要该图的边数: "); scanf("%d",&e); DG.n=n; DG.e=e; //给图赋值相应的顶点数及边数 for(k=0;k { fflush(stdin); printf("请输入第%d个顶点的信息: ",k+1); scanf("%c",&vt); DG.adjlist[k].vertex=vt; DG.adjlist[k].fristEdge=NULL; } //创建顶点的信息 printf("\n\t请选择你要创建的无向图: \n"); printf("**************************************\n"); printf("带权的有向图按1\n"); printf("不带权的有向图按2\n"); printf("**************************************\n"); scanf("%d",&k); if(k==1) { catch_Dvalues(&DG); } else { uncatch_Dvalues(&DG); } //上面的if--else中调用的函数必须是传地址的否则不会真正的赋值 returnDG; } /*为有向图创建边并且为边赋权值*/ voidcatch_Dvalues(ALGraph*DG) { intk,i,j; EdgeNode*en; EdgeTypeet; printf("\n注意顶点的信息,如果是从0开始的则没有问题! 否则边的两个端点要减一"); printf(",也就是说保证从0开始! \n"); for(k=0;k<(*DG).e;k++) { printf("请输入第%d条边所关联的两个顶点: ",k+1); scanf("%d%d",&i,&j); printf("请输入该边所带的权值: "); scanf("%d",&et); en=(EdgeNode*)malloc(sizeof(EdgeNode)); en->info=et; en->adjvertex=j; en->next=(*DG).adjlist[i].fristEdge; (*DG).adjlist[i].fristEdge=en; //因为图为有向图,所以只要关联一次.要区别无向图的创建 } } /*为有向图创建边并且不为边赋权值*/ voiduncatch_Dvalues(ALGraph*DG) { intk,i,j; EdgeNode*en; printf("\n注意顶点的信息,如果是从0开始的则没有问题! 否则边的两个端点要减一"); printf(",也就是说保证从0开始! \n"); for(k=0;k<(*DG).e;k++) { printf("请输入第%d条边所关联的两个顶点: ",k+1); scanf("%d%d",&i,&j); en=(EdgeNode*)malloc(sizeof(EdgeNode)); en->adjvertex=j; en->next=(*DG).adjlist[i].fristEdge; (*DG).adjlist[i].fristEdge=en; } } /* *函数功能: 创建一个无向图 *不需要参数 *返回值为无向图 */ ALGraphcreate_undALGraph() { ALGraphALG; intn,e; intk; VertexTypevt; printf("请输入要建立无向图的顶点数: "); scanf("%d",&n); printf("请输入要该图的边数: "); scanf("%d",&e); ALG.n=n; ALG.e=e; for(k=0;k { fflush(stdin); printf("请输入第%d个顶点的信息: ",k+1); scanf("%c",&vt); ALG.adjlist[k].vertex=vt; ALG.adjlist[k].fristEdge=NULL; } printf("\n\t请选择你要创建的无向图: \n"); printf("**************************************\n"); printf("带权的无向图按1\n"); printf("不带权的无向图按2\n"); printf("**************************************\n"); scanf("%d",&k); if(k==1) { catch_values(&ALG); } else { uncatch_values(&ALG); } //上面的if--else中调用的函数必须是传地址的否则不会真正的赋值 returnALG; } /* *函数功能: 不为图中的边带权,即创建图时,边没有带权 *入口参数为指向图的指针 *无返回值 */ voiduncatch_values(ALGraph*ALG) { intk,i,j; EdgeNode*en; tag=false; printf("\n注意顶点的信息,如果是从0开始的则没有问题! 否则边的两个端点要减一"); printf(",也就是说保证从0开始! \n"); for(k=0;k<(*ALG).e;k++) { printf("请输入第%d条边所关联的两个顶点: ",k+1); scanf("%d%d",&i,&j); en=(EdgeNode*)malloc(sizeof(EdgeNode)); en->adjvertex=j; en->next=(*ALG).adjlist[i].fristEdge; (*ALG).adjlist[i].fristEdge=en; //因为图为无向图,所以要两次分配单元 en=(EdgeNode*)malloc(sizeof(EdgeNode)); en->adjvertex=i; en->next=(*ALG).adjlist[j].fristEdge; (*ALG).adjlist[j].fristEdge=en; } } /* *函数功能: 为无向图中的边带权,即创建图时,边带有权值 *入口参数为指向图的指针 *无返回值 */ voidcatch_values(ALGraph*ALG) { intk,i,j; EdgeNode*en; EdgeTypeet; printf("\n注意顶点的信息,如果是从0开始的则没有问题! 否则边的两个端点要减一"); printf(",也就是说保证从0开始! \n"); tag=true; for(k=0;k<(*ALG).e;k++) { printf("请输入第%d条边所关联的两个顶点: ",k+1); scanf("%d%d",&i,&j); printf("请输入该边所带的权值: "); scanf("%d",&et); //以下要关联两次,因为无向图的边没有方向 en=(EdgeNode*)malloc(sizeof(EdgeNode)); en->info=et; en->adjvertex=j; en->next=(*ALG).adjlist[i].fristEdge; (*ALG).adjlist[i].fristEdge=en; en=(EdgeNode*)malloc(sizeof(EdgeNode)); en->info=et; en->adjvertex=i; en->next=(*ALG).adjlist[j].fristEdge; (*ALG).adjlist[j].fristEdge=en; } } /* *函数功能: 深度遍历图 *说明: 此函数中还调用DFS(ALGraphALG,intv)函数 *入口参数为图 *无返回值 */ voiddepth_Graph(ALGraphALG) { intk; intcount=0; for(k=0;k { visited[k]=false; }//标志每个顶点未被访问 printf("\n深度遍历图为: \n"); for(k=0;k { if(! visited[k]) { count++; DFS(ALG,k); } } printf("\n该图连通分量为: %d\n",count); } /* *函数功能: 深度遍历图 *入口参数ALG为图,v为遍历开始的节点 *无返回值 */ voidDFS(ALGraphALG,intv) { EdgeNode*p; printf("%c",ALG.adjlist[v].vertex); visited[v]=true; p=ALG.adjlist[v].fristEdge; while(p) { if(! visited[p->adjvertex]) { DFS(ALG,p->adjvertex); } p=p->next; } } /* *函数功能: 广度遍历图
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 建立 应用