这里使用了结构体,一个存储最短路径,一个存前一个结点。这样就可以根据最后一个结点往前找,找出整个路径。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define max 900000000 //表示两点之间无法连接
typedef struct{
int d;//到达某点的最短路径距离
int pre;//该最短路径是经过哪个点传过来的,用于存储路径
}path;
int main(){
int n,m,a,b,v,i,j,min,k;
char node[] = {"0ABCDEFGHIJKLMN"};//存储所有结点,加0是为了结点下标从1开始
char start1,last1;//初位置点
printf("请输入初末位置点:(空格隔开)\n");
scanf("%c %c",&start1,&last1);
int start2,last2;//初末位置点序号,一共点
//找出初末点对应的下标,和一共的点数
for(int i = 1;node[i]!='\0';i++)
{
if(node[i]==start1)
start2 = i;
if(node[i]==last1)
last2 = i;
n = i;//总点数
}
int e[n+1][n+1],vis[n+1];//e[i][j]表示i到j的边的权值,vis[i]表示此点是否被遍历
path to[n+1];//记录当前到某个点的最短路径
memset(vis,0,sizeof(vis));
for(i=0;i<=n;i++){
for(j=0;j<=n;j++){
e[i][j]=max;
}
to[i].d=max;
}
//存入图
e[1][2]=1,e[1][3]=1,e[1][4]=3;
e[2][7]=2;
e[3][5]=1;
e[4][13]=3;
e[5][6]=1;
e[6][9]=2;
e[7][10]=5;
e[9][12]=3;
e[10][12]=2;
e[11][12]=2,e[11][14]=6;
e[13][14]=5;
//变成无向图
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=n;j++)
{
if(e[i][j] != max)
e[j][i] = e[i][j];
}
}
//准备初始结点
for(i=1;i<=n;i++)
{
to[i].d=e[start2][i]; //初始化源点到i点边权值,之后过程中会发生变化
if(e[start2][i]!=max)
{
to[i].pre=start2;
}
}
vis[start2]=1;
for(i=1;i<=n-1;i++)
{//共循环n-1次,每循环一次,确定一条最短路,再次循环时这条路就不用考虑了,去寻找下一条最短路
min=max;
for(j=1;j<=n;j++)
{//寻找下一条当前最短路
if(to[j].d<min && vis[j]==0)
{
min=to[j].d;
k=j;
}
}
vis[k]=1;//找到了,到k点的路是当前最短路,标记它,根据它寻找下一条最短路
for(j=1;j<=n;j++)
{
if(e[k][j]<max)
{
if(to[j].d>to[k].d+e[k][j]&&vis[j]==0)
{//经过此k点到达j点的路径是否小于其他到达j点的路径
to[j].d=to[k].d+e[k][j];
to[j].pre=k;//改变j点是谁传来的,现在到j点的最短路径是经过k点的,由j点传来
}
}
}
}
if(to[last2].d != max)//判断是否能到达该点
{
char sort[14];
int count = 0;
printf("%c到%c最短距离为%d \n",node[start2],node[last2],to[last2].d);
j = last2;
sort[count] = node[j];
do{
j=to[j].pre;
count++;
sort[count] = node[j];//存储路径是逆序,需要正序输出
}while(j!=start2);
printf("最短路径为");
while(count>=1)//正序输出
{
printf("%c->",sort[count]);
count--;
}
printf("%c",sort[0]);
}
else
printf("无法到达该点!");
return 0;
}