一、BFS算法
(无权图、单源最短路径)
类似于BFS遍历及广度优先生成树,只不过加上了d\[\]和path\[\]数组,前者用于记录路径长度,后者用于记录由哪个顶点而来的路径。
手动模拟:
也就是BFS找相邻顶点

代码处理:

初始化

最后遍历之后:此处模拟从2到各顶点的单源路径


实现代码:
cpp
void BFS_MIN_Distance(Gaph G,int u){
for(int i = 0; i < G.vexnum; ++i){
d[i] = INT_MAX;//初始化路径长度
path[i] = -1; //最短路径从何而来
d[u] = 0;
visited[u] = true;
EnQueue(Q,u);
while(!isEmpty(Q)){
DeQueue(Q,u);//队头元素u出队
for(w = FirstNeighbor(G,u); w >= 0; w = NextNeighbor(G,u)){
if(!visited[w]){//w为u的尚未访问邻接顶点
d[w] = d[u] + 1;//路径长度+1
path[w] = u;//存路径
visited[w] = true;//w现在已经访问
EnQueue(Q,w);//w入队列
}
}
}
}
}
二、Dijkstra算法
(无权图+有权图、单源最短路径、不适用负权值)
1.构造
final :记录顶点是否用到
dist :记录从初始开始的最短路径长度
path :路径上的前驱

①初始:从v0开始初始化三个数组的信息

②第一轮:1)循环遍历所有结点,找到还没有用到的顶点,并且其dist最小Vi,令其final=true;
2)检查与Vi邻接的顶点,若其final为false,检查更新更小的dist。


③第二轮:


④第三轮:


⑤第四轮:

2.使用
**最短路径长度:**dist2表示从V0-V2最短路径长度为d2 = 9
**路径过程:**path2(V2) -> V1 -> V4 -> V0
3.时间复杂度 O(
)
三、Floyd算法
1.算法思想
Floyd算法:求出每一对顶点之间的最短路径
使用动态规划思想,将问题的求解分为多个阶段
对于n个顶点的图G,求任意一对顶点Vi一>Vj之间的最短路径可分为如下几个阶段:
#初始:不允许在其他顶点中转,最短路径是?
#0:若允许在Vo中转,最短路径是?
#1:若允许在Vo、V中转,最短路径是?
#2:若允许在Vo、V1、V2中转,最短路径是?
#n-1:若允许在Vo、V1、V2...Vn-1中转,最短路径是?
2.手动模拟





3.使用

注:不可以用于负权有环图。
4.代码
cpp
//准备工作,初始化矩阵A和path
for(int k = 0; k < n; k ++){ //遍历以Vk 作为中转点
for(int i = 0; i < n; i ++){ //遍历整个矩阵,i为行号,j为列号
foe(int j = 0; j < n; j ++){
if(A[i][j] > A[i][k]+A[k][j]){ //若以Vk作为中转点时路径更短
A[i][j] = A[i][k]+A[k][j]; //更新最短路径
path[i][j] = k; //记录中转点
}
}
}
}
5.复杂度
时间复杂度:O()
空间复杂度:O()
四、总结对比三种算法
| 特性 | BFS 算法 | Dijkstra 算法 | Floyd 算法 |
|---|---|---|---|
| 无权图 | ✓ | ✓ | ✓ |
| 带权图 | ✗ | ✓ | ✓ |
| 带负权值的图 | ✗ | ✗ | ✓ |
| 带负权回路的图 | ✗ | ✗ | ✗ |
| 时间复杂度 | O|V|^2 或 O(|V|+|E|) | O(|V|^2) | O(|V|^3) |
| 通常用于 | 求无权图的单源最短路径 | 求带权图的单源最短路径 | 求带权图中各顶点间的最短路径 |
注:也可用 Dijkstra 算法求所有顶点间的最短路径,重复 ∣V∣ 次即可,总的时间复杂度也是 O(∣V∣^3)
写在最后:本文章用于个人知识点总结,希望能够给你带来帮助。来源于王道数据结构课程。