图两点间的最短路径,所有路径算法C语言实现
2017-02-05 00:00
801 查看
#include<stdlib.h> #include<stdio.h> #include<string.h> #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 = 7fe0 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[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]<INFINITY) //存在路径 { 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]<min) //w顶点离v0顶点更近 { 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]))//更新当前最短路径及其距离 { 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<INFINITY&&p[a][b]) /* 如果景点一和它的一个临界点之间存在路径且最短路径 */ { 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]<INFINITY) { 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][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<k;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); } }
相关文章推荐
- 图两点间的最短路径,所有路径算法C语言实现
- 数据结构之---C语言实现最短路径之Dijkstra(迪杰斯特拉)算法
- 设计并实现求两点间所有路径的算法
- 数据结构之---C语言实现最短路径之Dijkstra(迪杰斯特拉)算法
- 任意两点间最短路径算法实现
- acm题目及我的程序(2)——Knight Moves (骑士跳跃) ——任意两点间的最短路径所有信息(算法1)
- 算法导论第二十五章-所有结点对的最短路径问题-Cpp代码实现
- 迪杰斯特拉最短路径算法C语言简单实现
- 图的邻接链表实现下的搜索两点之间所有路径的算法
- 任意两点间最短路径算法实现
- 图的邻接链表实现下的搜索两点之间所有路径的算法
- acm题目及我的程序(2)——Knight Moves (骑士跳跃) ——任意两点间的最短路径所有信息(算法2)
- 数据结构之---C语言实现最短路径之Floyd(弗洛伊德)算法
- 用最笨的方法,实现的最短路径算法(C语言)
- c语言实现求最短路径(迪杰斯特拉算法,《数据结构》算法7.15)
- 最短路径问题的算法实现【转载】
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 图论;单源最短路径;拓扑排序+松弛(有向无回路);Bellman-Ford(回路,负权回路);Dijkstra(无负权,可回路);可以用最小堆实现算法的优化;
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- dijkstra最短路径算法C实现