这个和我上一篇随笔差不多,只是不仅要知道给定点到所有其他点的最短路径,而且还要把路径给数出来,思想很好理解,如图:
顶点1到5的最短路径是14,具体路径是1-->4-->6-->5这个先后顺序是如何确定的?其实很简单,当你用Dijstra算法跑过一遍后,那么D[i]里的值就应该是最新的,也就是给定点到其他所有点的最短路劲长度已经确定了(下标从0开始),D[0]=0,D[1]=5,D[2]=9,D[3]=7,D[4]=14,D[5]=13,所以从这就可以看出D[5]<D[4],所以6在5的前面通过前面求出来的P[i][j]数组可以知道所要经过的点,而有D[i]数组又可以知道前后顺序,及要想输出路径,只要将所经过的点按D[i]的大小排序后再按从小到大的顺序输出即可。说的简单一点,也就是说这条路径上的点到源点的路径是在递增的,这个好理解吧,所以重点就在如何排序
定义一个结构体,用来保存节点到始点的路径长度和在图中的位置
typedef struct //路径结构体 { int index; int weight; }path;
路径只可能越来越长,所以按weight排序没有相同的元素,用qsort是稳定的,qsort比较函数
int comp(const void *a,const void *b) //qsort比较函数 { return (*(path *)a).weight-(*(path *)b).weight; }
关键代码在输出部分
for (i=0;i<g->vexnum;i++) { if (i!=v0) { printf("路径长度为:%d 路径为:",D[i]); int k=0,j; for (j=0;j<g->vexnum;j++) { if (P[i][j]==1&&(i!=j)) { path_point[k].index=j; path_point[k++].weight=D[j]; } } path_point[k].index=i; path_point[k++].weight=D[i]; qsort(path_point,k,sizeof(path),comp); for (j=0;j<k;j++) { if (j==0) { printf("%c",g->vexs[path_point[j].index]); } else { printf("-->%c",g->vexs[path_point[j].index]); } } printf("\n\n"); } }
项目的完整代码如下:
/*graph.h*/ //---------图的数组(邻接矩阵)存储表示---------- #include<stdio.h> #include <string.h> #include <stdlib.h> #define INFINITY 10000 //最大值 #define MAX_VERTEX_NUM 20 //最大顶点个数 typedef int VRType; typedef char VertexType; typedef char InfoType; typedef enum{DG,DN,UDG,UDN} GraphKind; //有向图,有向网,无向图,无向网 typedef struct ArcCell { VRType adj; //顶点关系类型,对无权图,有1或0表示是否相邻;对带权图,则为权值类型。 InfoType *info; //弧相关信息的指针 }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; typedef struct { VertexType vexs[MAX_VERTEX_NUM]; //顶点向量 AdjMatrix arcs; //邻接矩阵 int vexnum,arcnum; //图的当前顶点数和弧数 }mgraph,*MGraph; typedef struct //路径结构体 { int index; int weight; }path; int comp(const void *a,const void *b) //qsort比较函数 { return (*(path *)a).weight-(*(path *)b).weight; } int Locate_vexs(MGraph &g,VertexType v) //定位顶点位置 { for (int i=0;i<g->vexnum;i++) if (g->vexs[i]==v) return i; return -1; } void Print_mgraph(MGraph &g) //打印图 { int i; printf("邻接矩阵为:\n"); printf("┏ "); //五个空格 for (i=0;i<g->vexnum;i++) printf("%c ",g->vexs[i]); printf("\n\n"); for (i=0;i<g->vexnum;i++) { printf("%c ",g->vexs[i]); for (int j=0;j<g->vexnum;j++) { //输出矩阵,并且调整矩阵 if (g->arcs[i][j].adj>0&&g->arcs[i][j].adj<10) printf("%d ",g->arcs[i][j].adj); else if (g->arcs[i][j].adj>9&&g->arcs[i][j].adj<100) printf("%d ",g->arcs[i][j].adj); else if (g->arcs[i][j].adj>99&&g->arcs[i][j].adj<1000) printf("%d ",g->arcs[i][j].adj); else if (g->arcs[i][j].adj>999&&g->arcs[i][j].adj<10000) printf("%d ",g->arcs[i][j].adj); else if(g->arcs[i][j].adj==INFINITY) printf("∞ "); } printf("\n\n"); } } void Add_vexs(MGraph &g) //增加顶点 { printf("请输入顶点个数:"); scanf("%d",&g->vexnum); getchar(); //吸收回车符 printf("请输入顶点字符串序列:"); for (int i=0;i<g->vexnum;i++) scanf("%c",&g->vexs[i]); } void Add_arcs(MGraph &g) //增加边 { printf("请输入边的条数:"); scanf("%d",&g->arcnum); VertexType v1,v2; int row,col; VRType weight; printf("请输入权重和对应顶点,以空格隔开:\n"); for (int i=0;i<g->arcnum;i++) { scanf("%d %c %c",&weight,&v1,&v2); row=Locate_vexs(g,v1); col=Locate_vexs(g,v2); g->arcs[row][col].adj=weight; } } void Init_graph(MGraph &g) //初始化图 { g=(MGraph)malloc(sizeof(mgraph)); g->vexnum=0; g->arcnum=0; for (int i=0;i<MAX_VERTEX_NUM;i++) g->vexs[i]='0'; for (i=0;i<MAX_VERTEX_NUM;i++) for (int j=0;j<MAX_VERTEX_NUM;j++) { g->arcs[i][j].adj=INFINITY; g->arcs[i][j].info=NULL; } } void Create_mgraph(MGraph &g) //创建图 { Add_vexs(g); Add_arcs(g); }
代码和上一篇的改动不是太大,所以只给出部分截图: