一、引言
1.1用到的图概念
图的表示:一个图可以用数学语言描述为G(V(G),E(G))。V(vertex)指 的是图的顶点集,E(edge)指的是图的边集。
有向图vs无向图:根据边是否有方向,可将图分为有向图和无向图。
有权图:图的边上有权值。
图的邻接矩阵:
是对应n个点的n阶方阵,Dij表示第i个点到第j个点的距离。
对角线上是自己到自己的距离,为0;无向图第i个点到第j个点的距离=第j个点到第i个点的距离是对称矩阵。
负权回路:
存在一个环,且总路径距离是负数,每走一次路径距离都会变短,这样在求最短距离时会导致无限循环,使其没有最短路径。
1.2作图方法
1.利用matlab绘制
%Matlab作无向图
% (1)无权重(每条边的权重默认为1)
% 函数graph(s,t):可在 s 和 t 中的对应节点之间创建边,并生成一个图
% s 和 t 都必须具有相同的元素数;这些节点必须都是从1开始的正整数,或都是字符串元胞数组。
s1 = [1,2,3,4];
t1 = [2,3,1,1];
G1 = graph(s1, t1);
plot(G1)
%Matlab作有向图
% 函数graph(s,t,w):可在 s 和 t 中的对应节点之间以w的权重创建边,并生成一个图
s = [1,2,3,4];
t = [2,3,1,1];
w = [3,8,9,2];
G = graph(s, t, w);
plot(G, 'EdgeLabel', G.Edges.Weight, 'linewidth', 2)
2.利用画图网站:CS Academy
二、Dijkstra
Dijkstra 算法是一种用于寻找图中最短路径的算法(贪心算法)。
2.1基本思路:
1.设置起始点初始距离值(通常是 0),而其他点的距离值都设为无穷大。
2.它会从还没有确定最终最短距离的点中,选择距离起始点最近的那个点。
3.对于这个新选择的点的相邻点,计算从起始点经过这个新点到达相邻点的距离,并与之前设定的相邻点的距离值进行比较,如果新计算出来的距离更短,就更新相邻点的距离值。
就这样不断重复这个过程,直到到达终点,最终就找到了从起始点到终点的最短路径。
2.2动画演示:
ps:搬自【算法】最短路径查找—Dijkstra算法_哔哩哔哩_bilibili
缺点:无法处理负权重——用Ford算法解决
三、Ford
贝尔曼‐福特算法不再将节点区分为是否已访问的状态,利用循环来进行更新权重的,且每循环一次,贝尔曼福特算法都会更新所有的节点的信息(与Dijkstra的区别)
支持负权重,但不支持负权回路
3.1代码
[P,d] = shortestpath(G,start,end [,'Method',algorithm] )
[,‘Method’,algorithm]是可选的参数,表示计算最短路径的算法,默认使用的是“auto”。
例如:
[P,d] = shortestpath(G, 9, 4)
ps:上述代码就是在我们之前创建的图G的基础上,求9到4的最短距离
四、Floyd
Floyd 算法是一种用于寻找给定加权图中所有点对之间最短路径的算法,它的基本思想是通过动态规划来逐步更新图中各个顶点之间的最短距离。
支持负权重,但不支持负权回路
4.1基本思路
原理:
过程:
1.创建一个邻接矩阵和一个大小的path矩阵记录最短路径的中间顶点。
2.对于每一个中间顶点
k
,遍历所有的顶点对(i, j)
,检查通过中间顶点k
是否能得到更短的路径。比较当前
dist[i][j]
的值和dist[i][k] + dist[k][j]
的值,如果后者更小,就更新dist[i][j]
为dist[i][k] + dist[k][j]
,同时更新path[i][j]
为k。
不断重复这个过程,直到考虑完所有的顶点作为中间“中转站”。最终,dist
数组中存储的就是任意两个顶点之间的最短路径长度,而path
数组可以用于回溯得到具体的最短路径。
4.2代码
输入邻接矩阵D,调用函数
% 调用Floyd_algorithm函数求解
[dist,path] = Floyd_algorithm(D)