刚才又研究了bilibili懒猫老师的教学视频,对昨天的同样的Dijkstra算法进行改进。
昨天的文章里,我们用一个结构体变量,来存储两顶点间的最短路径的全部信息。
struct ShortestPath {
int pathLength ;
int indexOfVertexInPath[MAXVERTEX];
int numVertex;
};
这里的路径是完整路径,包括了路径里的所有顶点下标。
因为起点到最短路径里每一个顶点的路径都是最短路径(这个结论是我自己总结的,根据例题结果,还请大家一起斟酌,谢谢。这句总结也是程序里组织路径数据的核心理论依据。)所以我们还可以简化对最短路径里顶点信息的存储,只存储终点的前一个顶点位置即可。
懒猫老师的和课本里的程序,应该是这么个思路。
函数Dijkstra2ShortestPath:完成对图最短路径的计算,完成对distance[]和indexInPath[]的赋值。数组distance[]存储起点到各顶点的最短路径长度,数组indexInPath[]存储路径终点的前一个顶点在图顶点数组里的下标。
函数dispalyShortestPath:根据distance[]和indexInPath[]输出图的最短路径。因为其路径存储方式太深奥,故单独编写函数负责输出。
完整代码如下,先是main函数所在源文件:
#include<iostream>
#include<stdio.h>
using namespace std;
#define MAXVERTEX 15
#define INFINI 6000
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 6000
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, indexTemp;
for (int pathNum = 1; pathNum <= graphAdjMatrix.numVertexes - 1; pathNum++) {
for (indexUnCheck = 0; indexUnCheck < graphAdjMatrix.numVertexes; indexUnCheck++)
if (check[indexUnCheck] == false)
for (indexChecked = 0; indexChecked < graphAdjMatrix.numVertexes; indexChecked++)
if (indexChecked != indexStart &&
check[indexChecked] == true &&
graphAdjMatrix.edges[indexChecked][indexUnCheck] != INFINI &&
distance[indexUnCheck] > distance[indexChecked] + graphAdjMatrix.edges[indexChecked][indexUnCheck]) {
distance[indexUnCheck] = distance[indexChecked] + graphAdjMatrix.edges[indexChecked][indexUnCheck];
indexInPath[indexUnCheck] = indexChecked;
}
shortestTemp = INFINI;
for(indexUnCheck = 0 ; indexUnCheck < graphAdjMatrix.numVertexes ; indexUnCheck++)
if (check[indexUnCheck] == false && shortestTemp >= distance[indexUnCheck]) {
shortestTemp = distance[indexUnCheck];
indexTemp = indexUnCheck;
}
check[indexTemp] = true;
}
}
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;
}
}
测试结果和图和课本结果同上个文章,证明此程序里代码编写也是正确的。
谢谢阅读。