无权最短路
简单介绍
对于无权图G(边没有权值或认为权值为1),如果G是连通的,则每个顶点之间都存在路径。最短路径算法就是要找到一条连接不同顶点的最短路径。 例如:V2到V5可以是V2->V5,也可以是V2->V0->V3->V5,很明显最短路是前者
算法
主要思路: 广度优先搜索(bfs) :对于每个顶点,我们将跟踪三个信息 ,known标记此顶点是否被访问过,dist标记此顶点到起始点的深度,path标记前面的顶点,用于标记路径
步骤:我们以求V2到其他顶点的最短路为例)
- (1) 标记v2v2的Known为1,找与v2v2最近的点即遍历v2v2的邻接表,更新邻接表中的顶点v0、v5v0、v5的Known=1,dist=0+1=1,Path= v2v2。
- (2) 接着找离v0v0和v5v5的最近的点,对于v0v0,遍历其邻接表,更新v1v1和v3v3的相关状态。
- (3) 最终得到一个状态表,从改状态表中可以提取v2v2到其他所有顶点的最短路径。
- (4) 该方法的时间复杂度为 O(|V|^2)
伪代码:
void unweighted(table T)
{
int currdist;
vertex V, W;
for (currdist = 0; currdist < numvertex; currdist++)
{
for each vertex V
{
if (!T[V].know && T[V].dist == currdist)
{
T[V].known = true;
for each W adjacent to v;
if (T[W].dist == infinity)
{
T[W].path = V;
T[W].dist = currdist + 1;
}
}
}
}
}
优化(借助队列)
伪代码:
void unweighted(Table T)
{
queue Q;
vertex V, W;
Q = createQueue(numvertex);
enqueue(S, Q);
while (!isempty(Q))
{
V = Dequeue(Q);
T[V].known = true;
for each W adjacent to V
if (T[W].dist == Infinity)
{
T[W].dist = T[V].dist + 1;
T[W].path = V;
enqueue(W, Q);
}
}
Disposequeue(Q);
}
Dijkstra算法
伪代码讲解:
typedef int Vertex;
struct TableEntry
{
List Header;
int Known;
DistType Dist;
Vertex Path;
};
#define NotAvertex -1
typedef struct TableEntry Table[NumVertex];
void InitTable(Vertex Start,Vertex Graph G,Table T)
{
int i;
ReadGraph(G,T);
for(i=0;i<NumVertex;i++)
{
T[i].Known=False;
T[i].Dist=Infinity;
T[i].Path=NotAvertex;
}
T[Start].Dist=0;
}
void PrintPath(Vertex V,Table T)
{
if(T[V].Path!=NotAvertex)
{
PrintPath(T[V].Path,T);
printf(" to");
}
printf("%v",V);
}
void Dijkstra(Table T)
{
Vertex V,W;
for(;;)
{
V=smallest unknown distance vertex;
if(V==NotAvertex)break;
T[V].Known=True;
for each W adjacent to V
{
if(!T[W].Known)
{
if(T[V].Dist+Cvw<T[W].Dist)
{
T[W].Dist=T[V].Dist+Cvw
T[W].Path=V;
}
}
}
}
}
具有负边值的图的最短路算法
void weightedNegative(Table T)
{
queue Q;
vertex V, W;
Q = createQueue(numvertex);
MakeEmpty(Q);
enqueue(S, Q);
while (!isempty(Q))
{
V = Dequeue(Q);
for each W adjacent to V
if (T[W].Dist +Cvw<T[W].Dist)
{
T[W].dist = T[V].dist + Cvw;
T[W].path = V;
if(W is not already in Q)
enqueue(W, Q);
}
}
Disposequeue(Q);
}
此算法和无权的最短路算法很像,而且权值不是负的时候也同样可用
|