这个算法的 思想 根 求 最小生成树算法 普里姆(Prim)算法 极其相似。迪杰斯算法 是求 一个顶点 到其他 顶点的 最短路径算法。
下面 上代码:(用的是 邻接矩阵 表示法)
//迪杰斯特拉 最短路径。
//从 vex顶点 到其他 顶点的 最短路径
void shortestPath_Dij(MGraph g,char vex){
int loc = graphLocation(g,vex);
int minArray[MAX_VERTEX_NUM]={0};//最小路径值
bool final[MAX_VERTEX_NUM] = {false};//是否已经完成最小路径
//初始化vex 到vex 的 数据
minArray[loc] = 0;
final[loc] = true;
int path[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//路径数组,每一行 存放 vex 到这一行的 最短路径
int pathLenArray[MAX_VERTEX_NUM] = {0};//存放每行路径数组的个数.
for (int i = 0; i < g.vexNum; i++){
minArray[i] = g.arcs[loc][i].adj;
if (minArray[i] < INFINITY){//vex 指向 i
path[i][0] = i;
pathLenArray[i] = 1;
}
}
for (int i = 1; i < g.vexNum; i++)//g.verNum -1 个路径
{
int min = INFINITY;//最小路径值
int minIndex = -1;//当前最小路径索引
int notFind = -1;
for (int i = 0; i < g.vexNum; i++){//在 minArray 里 寻找 值最小的(不包括已完成的)
if (final[i] == false){
if (minArray[i] < min){
min = minArray[i];
minIndex = i;
}
else
{
notFind = i;
}
}
else if(final[i] == false){//没找到.
notFind = i;
}
}
if(minIndex == -1){//无路径时特殊处理
minIndex = notFind;
}
final[minIndex] = true;//设置 已找到 最小路径
//打印最小路径,以及 最小路径值
if (minIndex != notFind){
printf("%c 到 %c ,最小路径值为:%d,路径为:%c",vex,g.vexs[minIndex],min,vex);
}
else{
printf("%c 到 %c 不可达",vex,g.vexs[minIndex],min,vex);
}
int minLen = pathLenArray[minIndex];
for (int i = 0; i < minLen; i++){
printf("→ %c",g.vexs[path[minIndex][i]]);
}
printf("\n");
for (int i = 0; i < g.vexNum; i++){//重新 计算 最小路径 数组
if (final[i] == false){
int newMin = min + g.arcs[minIndex][i].adj;
if (newMin < minArray[i]){
minArray[i] = newMin;
//重新设置路径
int j;
for (j = 0; j < pathLenArray[minIndex]; j++){
path[i][j] = path[minIndex][j];
}
path[i][j] = i;
pathLenArray[i] = j+1;//设置数组长度.
}
}
}
}
}
在写 这段代码的时候遇到了两个问题:
1.数值 溢出,书中 用的 INT_MAX ,来表示 顶点之间 不可达的 关系。
当重新计算 最小路径数组的时候 int newMin = min + g.arcs[minIndex][i].adj; 如果 遇到了 INT_MAX,那么代码 逻辑 混乱。
所以 我把 INT_MAX 变成 短整型
#define INFINITY SHRT_MAX
2. 书中的 代码 当 没有 找到 最小值时,然后 访问 final数组 会 堆栈 溢出。加了一个特殊处理。
if(minIndex == -1){//无路径时特殊处理
minIndex = notFind;
}
完整源代码网盘地址:点击打开链接
运行截图: