有一幅无向图图
对应的邻接矩阵
char *vertexArray[8] = {"a", "v1", "v2", "v3", "v4", "v5", "v6", "b"};
int undiGraph[8][8] = {
//a,v1,v2,v3,v4,v5,v6, b
//a {X, 2, 8, 1, X, X, X, X}, //1+7+2+6
//v1 {2, X, 6, X, 1, X, X, X},
//v2 {8, 6, X, 7, 4, 2, 2, X},
//v3 {1, X, 7, X, X, X, 9, X},
//v4 {X, 1, 4, X, X, 3, X, 9},
//v5 {X, X, 2, X, 3, X, 4, 6},
//v6 {X, X, 2, 9, X, 4, X, 2},
//b {X, X, X, X, 9, 6, 2, X}
};
求从a到b的最短路径?
(使用“迪杰斯特拉算法”)解题过程:
1.先将“源顶点a”作为“轴心点”开始遍历所有可以抵达的“结点v1, v2, v3”,记录到达“结点v1, v2, v3”的路径值到对应的shortestPathsV[8] = {X(done), 2, 8, 1, X, X, X, X};
并且将“轴心点a”标记在flagV[8] = {1,0,0,0,0,0,0,0},标记为1后续不再使用此轴心点。
(注意:shortestPathsV[8]和flagV[8]每一项对应一个结点)
2.从shortestPathsV[8]中选择当前最短路径值"结点v3",遍历v3所有可以抵达的“结点v2, v6”,记录到达“v2, v6”的“路径值的和”到对应的shortestPathsV[8] = {X, 2, 8, 1(done), X, X, 1+9, X};
将“轴心点v3”标记在flagV[8] = {1,0,0,1,0,0,0,0}。
(注意:shortestPathsV[]只取到达该结点的最短路径值(之前取的较小值将被取代),与之前记录相等的值(v2)不改变))
3.从shortestPathsV[8]中选择当前最短路径值"结点v1"(排除a, v3),遍历v1所有可以抵达的“结点v2, v4”,记录到达“结点v2, v4”的“路径值的和”到对应的shortestPathsV[8] = {X, 2(done), 8, 1(done), 2+1, X, 1+9, X};
将“轴心点v3”标记在flagV[8] = {1,1,0,1,0,0,0,0}。
4.(排除a, v3, v1),从shortestPathsV[8]中选择当前最短路径值"结点v4", 遍历v4所有可以抵达的“结点v2, v5, b”,记录到达“结点v2, v5, b”的“路径值的和”到对应的shortestPathsV[8] = {X, 2(done), 2+1+4(替换8), 1(done), 3(done), 2+1+3, 1+9, 2+1+9};
将“轴心点v4”标记在flagV[8] = {1,1,0,1,1,0,0,0}。
5.(重复上述,遍历,更新shortestPathsV[8]和flagV[8])
选中v5,更新
shortestPathsV[8] = {X(done), 2(done), 7, 1(done), 3(done), 6(done), 10, 12}; //没有更新
将“轴心点v5”标记在flagV[8] = {1,1,0,1,1,1,0,0},
选中v2,更新
shortestPathsV[8] = {X(done), 2(done), 7(done), 1(done), 3(done), 6(done), 9, 12}; //更新到达6的值
将“轴心点v2”标记在flagV[8] = {1,1,1,1,1,1,0,0},
6.只剩下v6(除去b),更新v6可以抵达的值
shortestPathsV[8] = {X(done), 2(done), 7(done), 1(done), 3(done), 6(done), 9(done), 11};
将“轴心点v5”标记在flagV[8] = {1,1,1,1,1,1,1,0},
7.最后,只剩下终点值b(b已经在遍历的过程中被更新为最小值),即取得最小路径值11
#include <stdio.h>
#include<iostream.h>
#define N 8 //number of vertex
#define X 0XFFFF //no path
#define DONE 1 //traversed
#define UNDONE 0
int dijkstraAlg(int num, int undiGraph[][N], int startV, int endV, int preV[])
{
int shortestPathsV[num]; //shortestPathsV[num]表示从"源顶点"到"顶点num"的最短路径长度
bool flagV[num]; //flagV[num]标记"顶点num"是否(即将)作为轴点遍历;DONE表示被选中(即将)遍历。同时也表示已经求得到达该结点的最短路径。
int minWeight = X; //中间值,“当前最短路径值”;始终从“当前最短路径值”开始遍历
int minId;//“当前最短路径值”结点的ID
int tmpWeight = 0; //临时值,“当前路价值”;和pathsV[num]比较,如果小,则更新pathsV[num](为最短路径)
//初始化
for (int i=0; i<num; i++)
{
flagV[i] = UNDONE; //全部初始化未遍历
shortestPathsV[i] = undiGraph[startV][i]; //初始化"源顶点"能够到达的最短路径值(即undiGraph第1列的所有数据(也是第一行的所有数据))
preV[i] = -1; //途经结点数组
preV[i] = (undiGraph[startV][i] != X) ? startV : -1;
}
// shortestPathsV[startV] = -1; //起点标记为-1 不被更新
flagV[startV] = DONE; //标记"源顶点",表示已经求得到达该结点的最短路径
for (int i=1; i<num; i++) //还需要遍历n-1个顶点
{
minWeight = X;
//寻找下一个待加入的顶点(选轴心点)
for (int j=0; j<num; j++)
{
if (flagV[j]!=DONE && shortestPathsV[j]<minWeight)
{
minWeight = shortestPathsV[j]; //始终选择最小路径值和最小路径值对应的顶点
minId = j;
}
}
cout<<"i = "<<i<<" minId = "<<minId<<endl;
flagV[minId] = DONE; //flagV[minId] 值为DONE,后续不再选该数据
if (minId == endV) //最后一个结点已加入
{
return shortestPathsV[endV];
}
//选中轴点后,依次遍历该轴点可抵达的路径;
//在下面使用了遍历数组第二维的方式。
for (int j=0; j<num; j++)
{
if (minWeight==X || undiGraph[minId][j]==X) //遍历数组第二维
continue;
tmpWeight = minWeight + undiGraph[minId][j]; //当前轴点可抵达路径值
if(j!=startV && tmpWeight<shortestPathsV[j]) //起点无须更新;比较已经存档的路径值
{
shortestPathsV[j] = tmpWeight; //当前能够到达的最小路径值,替换之前保存的值
preV[j] = minId; //记录到达最小路径值的结点(ID)到preV中
}
cout<<"shortestPathsV["<<j<<"] = "<< shortestPathsV[j]<< " ";
cout<<"minId = "<<minId<<" ";
cout<<"preV["<<j<<"] = "<< preV[j]<<endl;
}
}
}
//print path
void printShortestPath(int num, int undiGraph[][N], int startV, int endV, const char **vertexArray)
{
int preV[num];//到达最小路径值的结点(ID),保存轴心结点
int shortestPath = dijkstraAlg(num, undiGraph, startV, endV, preV);
printf("the shortest path is: %d ", shortestPath);
int tmpPathsV = endV;
do
{
printf("%s <--- ", vertexArray[tmpPathsV]);//这里的用法很绕
tmpPathsV = preV[tmpPathsV];
}while(tmpPathsV != startV);
printf("%s\num", vertexArray[startV]);
}
//undirected graph
int main()
{
const char *vertexArray[N] = {"a", "v1", "v2", "v3", "v4", "v5", "v6", "b"};
int undiGraph[N][N] = {
//a,v1,v2,v3,v4,v5,v6, b
/*a*/ {X, 2, 8, 1, X, X, X, X}, //1+7+2+6
/*v1*/ {2, X, 6, X, 1, X, X, X},
/*v2*/ {8, 6, X, 7, 4, 2, 2, X},
/*v3*/ {1, X, 7, X, X, X, 9, X},
/*v4*/ {X, 1, 4, X, X, 3, X, 9},
/*v5*/ {X, X, 2, X, 3, X, 4, 6},
/*v6*/ {X, X, 2, 9, X, 4, X, 2},
/*b*/ {X, X, X, X, 9, 6, 2, X}
};
printShortestPath(N, undiGraph, 0, 7, vertexArray);
return 0;
}