图的建立和应用.docx

上传人:b****5 文档编号:30708708 上传时间:2023-08-19 格式:DOCX 页数:65 大小:27.48KB
下载 相关 举报
图的建立和应用.docx_第1页
第1页 / 共65页
图的建立和应用.docx_第2页
第2页 / 共65页
图的建立和应用.docx_第3页
第3页 / 共65页
图的建立和应用.docx_第4页
第4页 / 共65页
图的建立和应用.docx_第5页
第5页 / 共65页
点击查看更多>>
下载资源
资源描述

图的建立和应用.docx

《图的建立和应用.docx》由会员分享,可在线阅读,更多相关《图的建立和应用.docx(65页珍藏版)》请在冰豆网上搜索。

图的建立和应用.docx

图的建立和应用

一、实验目的

熟悉图的存储方式,实现图的邻接矩阵或者邻接表的存储方式下的基本运算,特别是深度遍历和广度遍历;掌握以图为基础的一些常用算法,如最小生成树、拓扑排序、最短路径等

二、需求分析

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;

}

}

/*

*函数功能:

广度遍历图

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1