数据结构最短路径例题_[数据结构笔记]16 最短路径问题

本文介绍了数据结构中的最短路径问题,包括单源多源最短路径算法。对于无权图,详细阐述了BFS算法实现单源最短路径,并分析了时间复杂度。接着讲解了Dijkstra算法用于有权图的单源最短路径,最后提到了多源图的Floyd算法及其适用场景。
摘要由CSDN通过智能技术生成

1、最短路径问题

单源多源、有权无权单源:固定起点,计算到其他每个顶点的最短路径,又分无权图 && 有权图

多源

2、无权图的单源最短路算法

1)思想:

路径长度为0的:起点

路径长度为1的:……

路径长度为2的:……

直到全部顶点都被访问到。

BFS遍历一次自然形成这个结果!

2)具体算法(类似BFS:访问入队-取元素如果子元素未访问,访问入队)第1个元素先访问再入队

此后,每从队列取元素,遍历邻接点,如果未访问,则先访问再入队

注意:出队的时候,出队元素已经访问过,所以要操作的是邻接点!

void UnWeighted(Vertex S){

dist[S] = 0;

Enqueue(Q, V);

while(!isEmpty(Q)):

{

Vertex V=DeQueue(Q);

for (V的每个邻接点W){

if (dist[V] == -1)

{

dist[W] = dist[V] + 1;

path[W] = V;#上一个节点

Enqueue(Q, W);

}

}

}

}

dist[W]和path[W] 分别记录距离和路径。

初始化:除开起点dist[W]=-1(不可能的值)

3)时间复杂度

如果是邻接表表示,O(V+E)

(拆成2部分看:enqueue和dequeue是一部分,其余是另一部分:每个V入队1次,出队1次;for (V的每个邻接点W),enqueue和dequeue合起来O(2V),其余for执行O(E),而O(2V+E)= O(V+E)

如果是邻接矩阵表示,enqueue和dequeue合起来O(2V),其余for执行O(V^2),合起来O(2V+V^2)= O(V^2)

4)代码示例

/* 邻接表存储 - 无权图的单源最短路算法 */

/* dist[]和path[]全部初始化为-1 */

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结束*/

}

3、有权图的单源最短路算法:Dijkstra算法

不考虑负值圈

最短路径算法广泛用于网络路由协议,最着名的是IS-IS(中间系统到中间系统)和开放最短路径优先(OSPF)

1)思路:

1)贪心算法:每次取weight最小的边,加入集合S

2)dist(v)最小的路径一定不经过S外面的顶点(证明:假设v是下一个要加入集合的点,如果有另外一个点w在S之外,v经过w的距离才是最小,那么一定sw<=sv,v下一个被收入,w必须已经收入S,矛盾)

3)加入新节点只可能影响到邻接点的dist(如果收录v使得s到w的路径变短,则s到w的路径一定经过v,且v到w有一条边直接相连 证明:如果w的路径,在v之后还有v-k-w,则k的dist一定比v的大,v是下一个收录的节点,说明k一定没被收录 ,而按照算法w的路径经过的点一定已经收录在集合内)

2)时间复杂度:

主要看未收录中dist最小的顶点 ,这一步怎么实现

dist初始化分3种

源点:dist为0;

源点的邻接点:权重;

其他:正无穷(以便发现更小更新)

3)代码示例:

/* 邻接矩阵存储 - 有权图的单源最短路算法 */

Vertex FindMinDist( MGraph Graph, int dist[], int collected[] )

{ /* 返回未被收录顶点中dist最小者 */

Vertex MinV, V;

int MinDist = INFINITY;

for (V=0; VNv; V++) {

if ( collected[V]==false && dist[V]

/* 若V未被收录,且dist[V]更小 */

MinDist = dist[V]; /* 更新最小距离 */

MinV = V; /* 更新对应顶点 */

}

}

if (MinDist < INFINITY) /* 若找到最小dist */

return MinV; /* 返回对应的顶点下标 */

else return ERROR; /* 若这样的顶点不存在,返回错误标记 */

}

bool Dijkstra( MGraph Graph, int dist[], int path[], Vertex S )

{

int collected[MaxVertexNum];

Vertex V, W;

/* 初始化:此处默认邻接矩阵中不存在的边用INFINITY表示 */

for ( V=0; VNv; V++ ) {

dist[V] = Graph->G[S][V];

if ( dist[V]

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; WNv; W++ ) /* 对图中的每个顶点W */

/* 若W是V的邻接点并且未被收录 */

if ( collected[W]==false && Graph->G[V][W]

if ( Graph->G[V][W]<0 ) /* 若有负边 */

return false; /* 不能正确解决,返回错误标记 */

/* 若收录V使得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; /* 算法执行完毕,返回正确标记 */

}

4、多源图的最短路径

1)对每个顶点做起点调用一次单源

对稀疏图,Vlog V,可以

对稠密图:V(V^2+E)

稀疏图:E约等于V

稠密图:E>>>>V

2)floyd算法适合稠密图

标准的O(V^3),没有V(V^2+E)的尾巴三重循环,V^3

3)代码示例

/* 邻接矩阵存储 - 多源最短路算法 */

bool Floyd( MGraph Graph, WeightType D[][MaxVertexNum], Vertex path[][MaxVertexNum] )

{

Vertex i, j, k;

/* 初始化 */

for ( i=0; iNv; i++ )

for( j=0; jNv; j++ ) {

D[i][j] = Graph->G[i][j];

path[i][j] = -1;

}

for( k=0; kNv; k++ )

for( i=0; iNv; i++ )

for( j=0; jNv; 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;

}

return true; /* 算法执行完毕,返回正确标记 */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值