c语言实现所有最短路径的存储,图两点间的最短路径,所有路径算法C语言实现...

本文档展示了如何创建一个无向图并实现迪杰斯特拉算法求两点间最短路径。代码中定义了图的结构,包括顶点信息和邻接矩阵,并提供了用户输入图数据或预设数据的选项。之后,通过迪杰斯特拉算法计算从指定起点到其他顶点的最短路径,并输出结果。此外,还包含了查找所有路径和查询景点信息的功能。
摘要由CSDN通过智能技术生成

#include

#include

#include

#define INFINITY 32768 //无穷大

#define MAX_VERTEX_NUM 11 //最大顶点数

typedef struct ArCell

{

int adj; //路径长度,对于无权图0-1-表示是否相邻,对于带权图则为权值

}ArCell;

typedef struct //图中顶点表示主要景点,存放景点的编号、名称、简介等信息,

{

char name[30]; //名称

int num; //编号

char introduction[100];//简介

}VertexDat; // 定义顶点的类型

typedef struct

{

VertexDat vexs[MAX_VERTEX_NUM]; //顶点数组

ArCell arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//邻接矩阵

int vexnum,arcnum; //顶点数,边数

}MGraph;//图的类型

MGraph *G; //图的类型,全局变量

/* 图的创建算法

输入顶点和边数,建立for循环输入景点编号,名称,简介,然后输入相邻景点的权值

并赋值给邻接矩阵所指的权值

*/

MGraph *CreatUDN(MGraph *G)//初始化图形,接受用户输入

{

int i,j,k,w;//i,j,k,w全为循环变量

char s[10] = "A";

#if 0

printf("请输入图的顶点数,弧数:");

scanf("%d%d",&G->vexnum,&G->arcnum); //输入顶点和边数

printf("请输入景点的编号:、名称、简介:\n"); //输入景点编号,名称,简介

for(i=1;i<=G->vexnum;i++)

{

printf("景点编号:");

scanf("%d",&G->vexs[i].num);

printf("景点名称:");

scanf("%s",G->vexs[i].name);

printf("景点简介:");

scanf("%s",G->vexs[i].introduction);

}

for(i=1;i<=G->vexnum;i++)

for(j=1;j<=G->vexnum;j++)

G->arcs[i][j].adj=INFINITY;

printf("请输入路径长度:\n"); //输入权值(路径长度)

for(k=1;k<=G->arcnum;k++)

{

printf("第%d条边:\n",k);

printf("景点对(i,j):"); //输入相邻景点

scanf("%d",&i);

scanf("%d",&j);

printf("路径长度:"); //输入相邻景点的权值

scanf("%d",&w);

G->arcs[i][j].adj=w; //把权值赋值给无向图G所指的邻接矩阵所指的权值

G->arcs[j][i]=G->arcs[i][j];// 下边是可直接到达的景点间的距离,由于两个景点间距离是互相的,

// 所以要对图中对称的边同时赋值。

}

#else

G->vexnum = 6;

G->arcnum = 14;

for(i=1;i<=G->vexnum;i++)

{

G->vexs[i].num = i;

strcpy(G->vexs[i].name, s);

strcpy(G->vexs[i].introduction, s);

*s += 1;

}

for(i=1;i<=G->vexnum;i++)

for(j=1;j<=G->vexnum;j++)

G->arcs[i][j].adj=INFINITY;

i = 1;j=2;

G->arcs[i][j].adj=1; //把权值赋值给无向图G所指的邻接矩阵所指的权值

G->arcs[j][i]=G->arcs[i][j];// 下边是可直接到达的景点间的距离,由于两个景点间距离是互相的,

// 所以要对图中对称的边同时赋值。

i = 2;j=1;

G->arcs[i][j].adj=1; //把权值赋值给无向图G所指的邻接矩阵所指的权值

G->arcs[j][i]=G->arcs[i][j];

i = 1;j=3;

G->arcs[i][j].adj=1; //把权值赋值给无向图G所指的邻接矩阵所指的权值

G->arcs[j][i]=G->arcs[i][j];

i = 3;j=1;

G->arcs[i][j].adj=1; //把权值赋值给无向图G所指的邻接矩阵所指的权值

G->arcs[j][i]=G->arcs[i][j];

i = 2;j=3;

G->arcs[i][j].adj=1; //把权值赋值给无向图G所指的邻接矩阵所指的权值

G->arcs[j][i]=G->arcs[i][j];

i = 3;j=2;

G->arcs[i][j].adj=1; //把权值赋值给无向图G所指的邻接矩阵所指的权值

G->arcs[j][i]=G->arcs[i][j];

i = 3;j=4;

G->arcs[i][j].adj=1; //把权值赋值给无向图G所指的邻接矩阵所指的权值

G->arcs[j][i]=G->arcs[i][j];

i = 4;j=3;

G->arcs[i][j].adj=1; //把权值赋值给无向图G所指的邻接矩阵所指的权值

G->arcs[j][i]=G->arcs[i][j];

i = 3;j=5;

G->arcs[i][j].adj=1; //把权值赋值给无向图G所指的邻接矩阵所指的权值

G->arcs[j][i]=G->arcs[i][j];

i = 5;j=3;

G->arcs[i][j].adj=1; //把权值赋值给无向图G所指的邻接矩阵所指的权值

G->arcs[j][i]=G->arcs[i][j];

i = 4;j=6;

G->arcs[i][j].adj=1; //把权值赋值给无向图G所指的邻接矩阵所指的权值

G->arcs[j][i]=G->arcs[i][j];

i = 6;j=4;

G->arcs[i][j].adj=1; //把权值赋值给无向图G所指的邻接矩阵所指的权值

G->arcs[j][i]=G->arcs[i][j];

i = 5;j=6;

G->arcs[i][j].adj=1; //把权值赋值给无向图G所指的邻接矩阵所指的权值

G->arcs[j][i]=G->arcs[i][j];

i = 6;j=5;

G->arcs[i][j].adj=1; //把权值赋值给无向图G所指的邻接矩阵所指的权值

G->arcs[j][i]=G->arcs[i][j];

#endif

printf("\t创建完毕!\n");

return G;

}

/* 两点之间最短路径算法(迪杰斯特拉算法)

1.将v0到其余顶点的最短路径长度初始化为权值: Dist[i]=G->arcs[v0][vi].adj;{vi属于V-S}

2.选择vk,使得Dist[i]=min(Dist[i]|vi属于V-S)

vk为目前求的下一条从v0出发的最短路径的终点

3.将vk加入S

4.修正从v0出发到集合V-S的任一顶点vi的最短路径的长度:从v0出发到集合V-S上任一顶点vi的当前最短路径长度为Dist[i]

从v0出发,中间经过新加入S的vk,然后到达集合V-S上任一顶点vi的路径长度为:

Dist[k]+G->arcs[v][w].adj

如果Dist[k]+G->arcs[v][w].adj

Dist[i]=Dist[k]+G->arcs[k][i].adj;

重复n-1次即可求出v0到其余顶点的最短路径

算法的时间复杂度为O(n*n).

*/

long int Dist[MAX_VERTEX_NUM]; // 辅助变量存储最短路径长度

int p[MAX_VERTEX_NUM ][MAX_VERTEX_NUM]; //起点到终点的路径数组

void ShortestPath_DIJ(MGraph *G,int v0)// 迪杰斯特拉算法来计算出起点到终点之间的最短路径,v0为起点

{

int v,w,i,min,x; //v,w,i,x为循环变量,min为最短长度

int path[MAX_VERTEX_NUM]; //存放最短路径

for(v=1;v<=G->vexnum;v++)

{

path[v]=0; //假设从顶点v0到顶点v没有最短路径

Dist[v]=G->arcs[v0][v].adj; //将与之相关的权值放入D中存放

for(w=1;w<=G->vexnum;w++)

p[v][w]=0; //设置为空路径

if(Dist[v]

{

p[v][v0]=1; //存在标志置为一

p[v][v]=1; //自身到自身

}

}

Dist[v0]=0;

path[v0]=1; //初始化v0顶点属于S集合

for(i=1;i<=G->vexnum;i++) //开始主循环,每一次求得v0到某个顶点的最短路径,并将其加入到S集合

{

min=INFINITY; //当前所知离顶点v0的最近距离

for(w=1;w<=G->vexnum;w++)

if(!path[w]) //w顶点在v-s中

if(Dist[w]

{

v=w;

min=Dist[w];//最短长度给min

}

path[v]=1; //离v0顶点更近的v加入到s集合

for(w=1;w<=G->vexnum;w++)

if(!path[w]&&(min+G->arcs[v][w].adj

{

Dist[w]=min+G->arcs[v][w].adj; // 不在s集合,并且比以前所找到的路径都短就更新当前路径

for(x=1;x<=G->vexnum;x++)

p[w][x]=p[v][x];

p[w][w]=1;

}

}

}//ShortestPath_DIJ end

void output(int sight1,int sight2) // 输出函数

{

int a,b,c,d,q=0;

a=sight2; /* 将景点二赋值给a */

if(a!=sight1) /* 如果景点二不和景点一输入重合,则进行... */

{

printf("\n\t从%s到%s的最短路径是",G->vexs[sight1].name,G->vexs[sight2].name);/* 输出提示信息 */

printf("\t(最短距离为 %dm.)\n\n\t",Dist[a]); /* 输出sight1到sight2的最短路径长度,存放在D[]数组中 */

printf("\t%s",G->vexs[sight1].name); /* 输出景点一的名称 */

d=sight1; /* 将景点一的编号赋值给d */

for(c=1;c<=MAX_VERTEX_NUM;c++)

{

gate:; /* 标号,可以作为goto语句跳转的位置 */

p[a][sight1]=0;

for(b=1;b<=MAX_VERTEX_NUM;b++)

{

if(G->arcs[d][b].adj

{

printf("-->%s",G->vexs[b].name); /* 输出此节点的名称 */

p[a][b]=0;

d=b; /* 将b作为出发点进行下一次循环输出,如此反复 */

goto gate;

}

}

}

}

}

int FindInformation(MGraph *G,char a[])// 查询各景点的相关信息

{

int i;

for(i=1;i<=G->vexnum;i++)

{

if(strcmp(G->vexs[i].name,a)==0)

break;

}

if(i==(G->vexnum+1))

{

return -1;

}

else

return G->vexs[i].num;

}

void Floyd(MGraph *G)

{

int v,u,i,w,k,j=0,flag=1,p[MAX_VERTEX_NUM][MAX_VERTEX_NUM][MAX_VERTEX_NUM],D[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

char A[10],B[10];

for(v=1;v<=G->vexnum;v++)

for(w=1;w<=G->vexnum;w++)

{

D[v][w]=G->arcs[v][w].adj;

for(u=1;u<=G->vexnum;u++)

p[v][w][u]=0;

if(D[v][w]

{

p[v][w][v]=1;p[v][w][w]=1;

}

}

for(u=1;u<=G->vexnum;u++)

for(v=1;v<=G->vexnum;v++)

for(w=1;w<=G->vexnum;w++)

if(D[v][u]+D[u][w]

{

D[v][w]=D[v][u]+D[u][w];

for(i=1;i<=G->vexnum;i++)

p[v][w][i]=p[v][u][i]||p[u][w][i];

}

printf("\t请输入起点的景点名称:\n");

scanf("%s",&A);

k=FindInformation(G,A);

if(k==-1){

printf("\t景点不存在!\n");

return ;

}

printf("\t请输入终点的景点名称:\n");

scanf("%s",&B);

k=FindInformation(G,B);

if(j==-1){

printf("\t景点不存在!\n");

return ;

}

printf("%s",G->vexs[k].name);

for(u=1;u<=G->vexnum;u++)

if(p[k][j][u]&&k!=u&&j!=u)

printf("-->%s",G->vexs[u].name);

printf("-->%s",G->vexs[j].name);

printf(" 总路线长%dm\n",D[k][j]);

}//Floyd end

int a=0;/*全局变量,用来记录每对顶点之间的所有路径的条数*/

int visited[MAX_VERTEX_NUM];/*全局数组,用来记录各顶点被访问的情况*/

int v[MAX_VERTEX_NUM];/*全局数组,用来存放路径上的各顶点*/

void path(MGraph *G,int i,int j,int k)

/*确定路径上第k+1个顶点的序号*/

{int s;

if(v[k]==j)/*找到一条路径*/

{

a++;/*路径的条数值加1*/

printf("第%d条:",a);

for(s=1;s

printf("%s->",G->vexs[v[s]].name);

printf("%s\n",G->vexs[v[s]].name);

}

s=1;

while(s<=G->vexnum)

{if(s!=i)/*保证找到的是简单路径*/

{

if(G->arcs[v[k]][s].adj!=INFINITY&&visited[s]==0)

/*当vk与vs之间有边存在且vs未被访问过*/

{visited[s]=1;/*置访问标志位为1,即已访问的*/

v[k+1]=s;/*将顶点s加入到v数组中*/

path(G,i,j,k+1);/*递归调用之*/

visited[s]=0;/*重置访问标志位为0,即未访问的,以便该顶点能被重新使用*/

}}

s++;

}

}

void disppath(MGraph *G,int i,int j)

{

int k;

v[1]=i;

for(k=1;k<=G->vexnum;k++)

visited[i]=0;/*初始化各顶点的访问标志位,即都为未访问过的*/

a=0;/*初始化路径的条数*/

path(G,i,j,1);/*通过调用path函数,找到从vi到vj的所有路径并输出*/

}

void SearchAllpath(MGraph *G)/*查询两个景点间的所有路径*/

{ int i,j;

char b[10],c[10];

printf("请输入源点景点名称:");

scanf("%s",&b);

i=FindInformation(G,b);

getchar();

if(i==-1)

{

printf("你输入的源点景点名称不存在!\n");

return;

}

printf("请输入终点景点名称:");

scanf("%s",&c);

j=FindInformation(G,c);

getchar();

if(j==-1)

{

printf("你输入的终点景点名称不存在!\n");

return;

}

printf("从%s到%s的所有游览路径有:\n",G->vexs[i].name,G->vexs[j].name);/*输出出发景点和目地景点的名称*/

disppath(G,i,j);/*调用disppath函数,用来输出两个景点间的所有路径*/

}

char SearchMenu() /* 查询子菜单 */

{

char c;

int flag;

do{

flag=1;

system("cls");

printf("\n\t\t┏━━━━━━━━━━━━━━━┑\n");

printf("\t\t\t┃ ┃\n");

printf("\t\t\t┃ 1、按照景点编号查询 ┃\n");

printf("\t\t\t┃ 2、按照景点名称查询 ┃\n");

printf("\t\t\t┃ 0、返回 ┃\n");

printf("\t\t\t┃ ┃\n");

printf("\t\t\t┗━━━━━━━━━━━━━━━┛\n");

printf("\t\t\t\t请输入您的选择:");

scanf("%c",&c);

if(c=='1'||c=='2'||c=='0')

flag=0;

}while(flag);

return c;

}

void search(MGraph *G) /* 查询景点信息 */

{

int num;

int i;

char c;

char name[20];

do

{

system("cls");

c=SearchMenu();

switch (c)

{

case '1':

system("cls");

printf("\n\n\t\t请输入您要查找的景点编号:");

scanf("%d",&num);

for(i=1;i<=MAX_VERTEX_NUM;i++)

{

if(num==G->vexs[i].num)

{

printf("┏━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓\n");

printf("┃编号┃景点名称 ┃简介 ┃\n");

printf("┃%-4d %-16s┃%-56s┃\n",G->vexs[i].num,G->vexs[i].name,G->vexs[i].introduction);

printf("┗━━┻━━━━━━━━┻━━━━━━━━━━━━━━━━━━┛\n");

printf("\n\t\t\t按任意键返回...");

getchar();

getchar();

break;

}

}

if(i==MAX_VERTEX_NUM)

{

printf("\n\n\t\t\t没有找到!");

printf("\n\n\t\t\t按任意键返回...");

getchar();

getchar();

}

break;

case '2':

system("cls");

printf("\n\n\t\t请输入您要查找的景点名称:");

scanf("%s",&name);

for(i=1;i<=MAX_VERTEX_NUM;i++)

{

if(!strcmp(name,G->vexs[i].name))

{

printf("┏━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓\n");

printf("┃编号┃景点名称 ┃简介 ┃\n");

printf("┃%-4d %-16s┃%-56s┃\n",G->vexs[i].num,G->vexs[i].name,G->vexs[i].introduction);

printf("┗━━┻━━━━━━━━┻━━━━━━━━━━━━━━━━━━━┛\n");

printf("\n\t\t\t按任意键返回...");

getchar();

getchar();

break;

}

}

if(i==MAX_VERTEX_NUM)

{

printf("\n\n\t\t\t没有找到!");

printf("\n\n\t\t\t按任意键返回...");

getchar();

getchar();

}

break;

}

}while(c!='0');

}

void Menu()

{

printf("\n 学校导游图\n");

printf(" ┏━━━━━━━━━━━━━━━━━━━━┓\n");

printf(" ┃ 1.浏览校园全景 ┃\n");

printf(" ┃ 2.查询图中任意两个景点间的最短路径 ┃\n");

printf(" ┃ 3.查询图中任意两个景点间的所有路径 ┃\n");

printf(" ┃ 4.查看景点信息 ┃\n");

printf(" ┃ 5.退出系统 ┃\n");

printf(" ┗━━━━━━━━━━━━━━━━━━━━┛\n");

printf("请选择:");

}

void Browser(MGraph *G)

{

int i;

printf("┏━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓\n");

printf("┃编号┃景点名称 ┃简介 ┃\n");

for(i=1;i<=G->vexnum;i++)

printf("┃%-4d┃%-16s┃%-56s┃\n",G->vexs[i].num,G->vexs[i].name,G->vexs[i].introduction);

printf("┗━━┻━━━━━━━━┻━━━━━━━━━━━━━━━━━━━┛\n");

}

void main(void)

{

int i;

int v0,v1;

G=(MGraph *)malloc(sizeof(MGraph));

G=CreatUDN(G);

Menu();

scanf("%d",&i);

while(i!=5)

{

switch(i)

{

case 1:system("cls");Browser(G);Menu();break;

case 2:system("cls");

printf("\n\n\t\t\t请选择起点景点:");

scanf("%d",&v0);

printf("\t\t\t请选择终点景点:");

scanf("%d",&v1);

ShortestPath_DIJ(G,v0); /* 计算两个景点之间的最短路径 */

output(v0,v1); /* 输出结果 */

Menu();break;

case 3:system("cls");

// Floyd(G);

SearchAllpath(G);

Menu();break;

case 4:system("cls");search(G);Menu();break;

case 5:exit(1);break;

default:break;

}

scanf("%d",&i);

}

}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值