最短路径算法
常见问题:
求小区最短路径、求地铁最短路径、求给出图线之间从一点到另外一点的最短距离、求解所有的最短路径等
思路:
(1)将所有的点转换成Graph;(2)套用Floyd算法或者Dijkstra算法求解出最短路径。
算法实现:
(1)Floyd算法:http://www.cnblogs.com/skywang12345/p/3711523.html
// 邻接矩阵 typedef struct _graph { char vexs[MAX]; // 顶点集合 int vexnum; // 顶点数 int edgnum; // 边数 int matrix[MAX][MAX]; // 邻接矩阵 }Graph, *PGraph;
/* * floyd最短路径。 * 即,统计图中各个顶点间的最短路径。 * * 参数说明: * G -- 图 * path -- 路径。path[i][j]=k表示,"顶点i"到"顶点j"的最短路径会经过顶点k。 * dist -- 长度数组。即,dist[i][j]=sum表示,"顶点i"到"顶点j"的最短路径的长度是sum。 */ void floyd(Graph G, int path[][MAX], int dist[][MAX]) { int i,j,k; int tmp; // 初始化 for (i = 0; i < G.vexnum; i++) { for (j = 0; j < G.vexnum; j++) { dist[i][j] = G.matrix[i][j]; // "顶点i"到"顶点j"的路径长度为"i到j的权值"。 path[i][j] = j; // "顶点i"到"顶点j"的最短路径是经过顶点j。 } } // 计算最短路径 for (k = 0; k < G.vexnum; k++) { for (i = 0; i < G.vexnum; i++) { for (j = 0; j < G.vexnum; j++) { // 如果经过下标为k顶点路径比原两点间路径更短,则更新dist[i][j]和path[i][j] tmp = (dist[i][k]==INF || dist[k][j]==INF) ? INF : (dist[i][k] + dist[k][j]); if (dist[i][j] > tmp) { // "i到j最短路径"对应的值设,为更小的一个(即经过k) dist[i][j] = tmp; // "i到j最短路径"对应的路径,经过k path[i][j] = path[i][k]; } } } } // 打印floyd最短路径的结果 printf("floyd: \n"); for (i = 0; i < G.vexnum; i++) { for (j = 0; j < G.vexnum; j++) printf("%2d ", dist[i][j]); printf("\n"); } }
(2)Dijkstra算法实现:http://www.cnblogs.com/skywang12345/p/3711512.html
// 邻接矩阵 typedef struct _graph { char vexs[MAX]; // 顶点集合 int vexnum; // 顶点数 int edgnum; // 边数 int matrix[MAX][MAX]; // 邻接矩阵 }Graph, *PGraph; // 边的结构体 typedef struct _EdgeData { char start; // 边的起点 char end; // 边的终点 int weight; // 边的权重 }EData;
/* * Dijkstra最短路径。 * 即,统计图(G)中"顶点vs"到其它各个顶点的最短路径。 * * 参数说明: * G -- 图 * vs -- 起始顶点(start vertex)。即计算"顶点vs"到其它顶点的最短路径。 * prev -- 前驱顶点数组。即,prev[i]的值是"顶点vs"到"顶点i"的最短路径所经历的全部顶点中,位于"顶点i"之前的那个顶点。 * dist -- 长度数组。即,dist[i]是"顶点vs"到"顶点i"的最短路径的长度。 */ void dijkstra(Graph G, int vs, int prev[], int dist[]) { int i,j,k; int min; int tmp; int flag[MAX]; // flag[i]=1表示"顶点vs"到"顶点i"的最短路径已成功获取。 // 初始化 for (i = 0; i < G.vexnum; i++) { flag[i] = 0; // 顶点i的最短路径还没获取到。 prev[i] = 0; // 顶点i的前驱顶点为0。 dist[i] = G.matrix[vs][i];// 顶点i的最短路径为"顶点vs"到"顶点i"的权。 } // 对"顶点vs"自身进行初始化 flag[vs] = 1; dist[vs] = 0; // 遍历G.vexnum-1次;每次找出一个顶点的最短路径。 for (i = 1; i < G.vexnum; i++) { // 寻找当前最小的路径; // 即,在未获取最短路径的顶点中,找到离vs最近的顶点(k)。 min = INF; for (j = 0; j < G.vexnum; j++) { if (flag[j]==0 && dist[j]<min) { min = dist[j]; k = j; } } // 标记"顶点k"为已经获取到最短路径 flag[k] = 1; // 修正当前最短路径和前驱顶点 // 即,当已经"顶点k的最短路径"之后,更新"未获取最短路径的顶点的最短路径和前驱顶点"。 for (j = 0; j < G.vexnum; j++) { tmp = (G.matrix[k][j]==INF ? INF : (min + G.matrix[k][j])); // 防止溢出 if (flag[j] == 0 && (tmp < dist[j]) ) { dist[j] = tmp; prev[j] = k; } } } // 打印dijkstra最短路径的结果 printf("dijkstra(%c): \n", G.vexs[vs]); for (i = 0; i < G.vexnum; i++) printf(" shortest(%c, %c)=%d\n", G.vexs[vs], G.vexs[i], dist[i]); }