求图里顶点的最短路径,Dijkstra算法是单源点路径。求的是源点到其他所有顶点的最短路径。昨天刚发了两篇文章,关于Dijkstra算法,但里面的函数Dijkstra2ShortestPath,时间复杂度是O(n^3),课本给的同样的函数,时间复杂度是O(n ^ 2),经过仔细思考。课本也是正确的。跟着bilibili懒猫老师,思路是理解了。但具体代码,这一个自己摸索,还是很曲折的。因为懒猫老师,在她视频里,给了一个调用的函数名,没有给出这个被调用的具体函数。离了懒猫老师,学起来真难。课本里的i j k,实在阅读不下去。
Dijkstra算法可以概括为,把包括源点在内的已求出最短路径的顶点,归为一个点集,剩下没有求出最短路径的终点归为一个点集。依据路径递增的顺序,依次求出所有最短路径。最开始时,源点集里只有它自己,自此开始,每求得一个最短路径,除了更改其所属点集外,还结合这个最新求出的最短路径,修正那些未求出最短路径的终点的路径值。怎么修正呢?换句话说,就是看看途径这个新的最短路径,到达那些终点时,会不会把路径缩短。因为我们存储的路径,只是存储每个终点的前一个顶点的下标。
举例来说,有顶点A B C D,A为起点。先找到A——>B为最短路径,我们接着修正A——>C和A——>D的路径长度,如果A——>B——>C和A——>B——>D的路径更短,就更新distan[]和indexInPath[]数组的值。前者保存了起点到达每个终点的路径长度,后者保存了每个终点的在最短路径里的前一个顶点的下标。
换句话说,函数执行中某一时刻,我们有多个终点未找到其最终最短路径,但distan[]和indexInPath[]数组,仍然为这些终点保存有数值,这些计算值,是这些终点在当时已知的最短路径情形下能选择能找到的当时情况下的最短路径信息。其信息不断变更,直到所有终点都进入起点所在点集。这两个数组的信息才不再有任何改变。
这三篇文章里,本次只有函数Dijkstra2ShortestPath重写了。其他函数同第二篇,没有任何改变。这次和课本程序完全一样了,除了变量命名。但仍给出全部代码。
main函数源文件代码:
#include<iostream>
#include<stdio.h>
using namespace std;
#define MAXVERTEX 15
#define INFINI 10000
struct GraphAdjaMatrix {
char vertexes[MAXVERTEX];
int edges[MAXVERTEX][MAXVERTEX];
int numVertexes;
int numEdges;
};
extern void createGraphAdjMatrix(GraphAdjaMatrix &graphAdjMatrix,
int numVertexes,int numEdges,int edges[][7],char vertexes[]);
extern void dispalyGraphAdjMatrix(GraphAdjaMatrix &graphAdjMatrix);
extern void Dijkstra2ShortestPath(GraphAdjaMatrix& graphAdjMatrix,
int distance[],int indexInPath[], int indexStart);
extern void dispalyShortestPath(GraphAdjaMatrix& graphAdjMatrix,
int distance[], int indexInPath[], int indexStart);
int main() {
GraphAdjaMatrix graphAdjMatrix ;
int numVertexes = 7, numEdges = 12;
int edges[][7] = { {0,4,6,6,INFINI,INFINI,INFINI},
{INFINI,0,1,INFINI,7,INFINI,INFINI},
{INFINI,INFINI,0,INFINI,6,4,INFINI},
{INFINI,INFINI,2,0,INFINI,5,INFINI},
{INFINI,INFINI,INFINI,INFINI,0,INFINI,6},
{INFINI,INFINI,INFINI,INFINI,1,0,8},
{INFINI,INFINI,INFINI,INFINI,INFINI,INFINI,0} };
char vertexes[] = {'0','1','2','3','4','5','6'};
createGraphAdjMatrix(graphAdjMatrix,numVertexes,numEdges,edges,vertexes);
dispalyGraphAdjMatrix(graphAdjMatrix);
cout << endl;
int distance[MAXVERTEX], indexInPath[MAXVERTEX];
Dijkstra2ShortestPath(graphAdjMatrix,distance,indexInPath,0);
cout << endl << "shortest path : " << endl;
dispalyShortestPath(graphAdjMatrix,distance,indexInPath,0);
return 0;
}
各函数所在源文件代码:
#include<iostream>
#include<stdio.h>
using namespace std;
#define MAXVERTEX 15
#define INFINI 10000
struct GraphAdjaMatrix {
char vertexes[MAXVERTEX];
int edges[MAXVERTEX][MAXVERTEX];
int numVertexes;
int numEdges;
};
void createGraphAdjMatrix(GraphAdjaMatrix &graphAdjMatrix,
int numVertexes, int numEdges, int edges[][7], char vertexes[]) {
graphAdjMatrix.numVertexes = numVertexes;
graphAdjMatrix.numEdges = numEdges;
for (int i = 0; i < numVertexes; i++)
graphAdjMatrix.vertexes[i] = vertexes[i];
for (int row = 0; row < numVertexes; row++)
for (int column = 0; column < numVertexes; column++)
graphAdjMatrix.edges[row][column] = edges[row][column];
}
void dispalyGraphAdjMatrix(GraphAdjaMatrix &graphAdjMatrix) {
cout << "adjacensy matrix :" << endl;
int row,column;
printf("%3c",' ');
for (row = 0; row < graphAdjMatrix.numVertexes; row++)
printf("%3c",graphAdjMatrix.vertexes[row]);
printf("\n");
for (row = 0; row < graphAdjMatrix.numVertexes; row++) {
printf("%-3c", graphAdjMatrix.vertexes[row]);
for (column = 0; column < graphAdjMatrix.numVertexes; column++)
if (graphAdjMatrix.edges[row][column] == INFINI)
printf("%3s", "∞");
else
printf("%3d",graphAdjMatrix.edges[row][column]);
cout << endl;
}
}
void Dijkstra2ShortestPath(GraphAdjaMatrix& graphAdjMatrix,
int distance[], int indexInPath[], int indexStart) {
for (int i = 0; i < graphAdjMatrix.numVertexes; i++) {
distance[i] = graphAdjMatrix.edges[indexStart][i];
indexInPath[i] = indexStart;
}
bool check[MAXVERTEX] = { false };
check[indexStart] = true;
int indexUnCheck, indexChecked;
int shortestTemp, indexEndTemp;
for (int pathNum = 1; pathNum <= graphAdjMatrix.numVertexes - 1; pathNum++) {
shortestTemp = INFINI;
for (indexUnCheck = 0; indexUnCheck < graphAdjMatrix.numVertexes; indexUnCheck++)
if (check[indexUnCheck] == false && shortestTemp >= distance[indexUnCheck]) {
shortestTemp = distance[indexUnCheck];
indexEndTemp = indexUnCheck;
}
check[indexEndTemp] = true;
for (indexUnCheck = 0; indexUnCheck < graphAdjMatrix.numVertexes; indexUnCheck++)
if (check[indexUnCheck] == false &&
graphAdjMatrix.edges[indexEndTemp][indexUnCheck] != INFINI &&
distance[indexUnCheck] > distance[indexEndTemp] + graphAdjMatrix.edges[indexEndTemp][indexUnCheck]) {
distance[indexUnCheck] = distance[indexEndTemp] + graphAdjMatrix.edges[indexEndTemp][indexUnCheck];
indexInPath[indexUnCheck] = indexEndTemp;
}
}
}
void dispalyShortestPath(GraphAdjaMatrix& graphAdjMatrix,
int distance[], int indexInPath[], int indexStart) {
char startVertex = graphAdjMatrix.vertexes[indexStart];
char arrayTemp[MAXVERTEX];
int lengthTemp,indexTemp;
for (int index = 0; index < graphAdjMatrix.numVertexes ; index++)
if (index != indexStart) {
cout << "from " << startVertex << " to " << graphAdjMatrix.vertexes[index] << " , ";
cout << " path length : ";
printf("%-2d , path : ", distance[index]);
lengthTemp = 0;
arrayTemp[lengthTemp] = graphAdjMatrix.vertexes[index];
lengthTemp++;
indexTemp = indexInPath[index];
while (indexTemp != indexStart) {
arrayTemp[lengthTemp] = graphAdjMatrix.vertexes[indexTemp];
lengthTemp++;
indexTemp = indexInPath[indexTemp];
}
arrayTemp[lengthTemp] = graphAdjMatrix.vertexes[indexTemp];
for (; lengthTemp >= 0; lengthTemp--)
cout << arrayTemp[lengthTemp] << " ";
cout << endl;
}
}
测试结果同第二篇,第一篇,完全一模一样,和课本也一样。代码也是全部正确的。谢谢阅读。