一、无权图的单源最短路算法
void Unweighted(LGraph Graph, int dist[], int path[], Vertex S)
{
Queue Q;
Vertex V;
PtrToAdjVNode W;
Q = CreateQueue(Graph->Nv); // 创建空队列,MaxSize为外部定义的常数
dist[S] = 0; // 初始化源点
AddQ(Q, S);
while (!IsEmpty(Q)) {
V = DeleteQ(Q);
for (W=Graph->G[V].FirstEdge; W; W=W->Next) // 对V的每个邻接点W->AdjV
if (dist[W->AdjV]==-1) { // 若W->AdjV未被访问过
dist[W->AdjV] = dist[V] + 1; // W->AdjV到S的距离更新
path[W->AdjV] = V; // 将V记录在S到W->AdjV的路径上
AddQ(Q, W->AdjV);
}
} // while结束
}
二、有权图的单源最短路算法
2.1 Djkstra
- 伪码描述
(1)初始化,将所有顶点的dist设置为
∞
\infin
∞,path设置为-1;
然后设置
v
1
v_1
v1的dist为0,
v
2
v_2
v2的dist为2,path为1,
v
4
v_4
v4的dist为1,path为1;
(2)正式进入Dijkstra算法,找到
v
4
v_4
v4,并收录它,分别更新未收录的
v
3
v_3
v3、
v
5
v_5
v5、
v
6
v_6
v6、
v
7
v_7
v7的dist值为3,3,9,5,并更新他们的path都为4;
(3)找到未收录顶点中dist最小者为
v
2
v_2
v2,收录它,由于它的邻接点都不符合循环的要求,未做任何更新;
(4)找到未收录顶点中dist最小者为
v
3
v_3
v3(
v
5
v_5
v5也可以),收录它,由于它的邻接点
v
6
v_6
v6符合要求,将
v
6
v_6
v6的dist从9更新为8,path从4更新为3;
(5)重复上述操作,直至所有顶点被收录,相应的dist和path都被更新完成,退出程序;
- 代码
Vertex FindMinDist(MGraph Graph, int dist[], int collected[])
{ // 返回未被收录顶点中dist最小者
Vertex MinV, V;
int MinDist = INFINITY;
for (V=0; V<Graph->Nv; V++) {
if (collected[V]==false && dist[V]<MinDist) {
// 若V未被收录,且dist[V]更小
MinDist = dist[V]; // 更新最小距离
MinV = V; // 更新对应顶点
}
}
if (MinDist < INFINITY) // 若找到最小dist
return MinV; // 返回对应的顶点下标
else
return EROOR; // 若这样的顶点不存在,返回错误标记
}
bool Dijkstra(MGraph Graph, int dist[], int path[], Vertex S)
{
int collected[MaxVertexNum];
Vertex V, W;
// 初始化:此处默认邻接矩阵中不存在的边用INFINITY表示
for ( V=0; V<Graph->Nv; V++ ) {
dist[V] = Graph->G[S][V];
if ( dist[V]<INFINITY )
path[V] = S;
else
path[V] = -1;
collected[V] = false;
}
// 先将起点收入集合
dist[S] = 0;
collected[S] = true;
while (1) {
// V = 未被收录顶点中dist最小者
V = FindMinDist(Graph, dist, collected);
if ( V==ERROR ) // 若这样的V不存在
break; // 算法结束
collected[V] = true; // 收录V
for ( W=0; W<Graph->Nv; W++ ) { // 对图中的每个顶点W
// 若W是V的邻接点并且未被收录
if ( collected[W]==false && Graph->G[V][W]<INFINITY) {
if ( Graph->G[V][W]<0 ) { // 若有负边
return false; // 不能正确解决,返回错误标记
}
// 若收录使得dist[W]变小
if ( dist[V]+Graph->G[V][W] < dist[W] ) {
dist[W] = dist[V] + Graph->G[V][W]; // 更新dist[W]
path[W] = V; // 更新S到W的路径
}
}
}
} // while 结束
return true; // 算法执行完毕,返回正确标记
}
2.2 Floyd
bool Floyd( MGraph Graph, WeightType D[][MaxVertexNum], Vertex path[][MaxVertexNum])
{
Vertex i, j, k;
// 初始化
for ( i=0; i<Graph->Nv; i++ ) {
for ( j=0; j<Graph->Nv; j++) {
D[i][j] = Graph->G[i][j];
path[i][j] = -1;
}
}
for ( k=0; k<Graph->Nv; k++) {
for ( i=0; i<Graph->Nv; i++ ) {
for ( j=0; j<Graph->Nv; j++ ) {
if ( D[i][k] + D[k][j] < D[i][j] ) {
D[i][j] = D[i][k] + D[k][j];
if ( i==j && D[i][j]<0) // 若发现负值圈
return false; // 不能正确解决,返回错误标记
path[i][j] = k;
}
}
}
} // for循环结束
return true; // 算法执行完毕,返回正确标记
}