图的基本概念
- 图论中的图(Graph)是由若干给定的点及连接两点的线所构成的图形,这种图形通常用来描述某些事物之间的某种特定关系,用点代表事物,用连接两点的线表示相应两个事物间具有这种关系。
- 一个图可以用数学语言描述:G(V(G),E(G))。其中V(vertex)指的是图的顶点集,E(edge)指的是图的边集。
- 根据边是否有方向,可将图分为有向图和无向图。
- 有些图的边上还可能有权值,这样的图称为有权图。
- 在线作图网址:https://csacademy.com/app/graph_editor/
举例
1.无向图的权重邻接矩阵
则:
D
=
[
0
Inf
3
3
Inf
0
Inf
5
3
Inf
0
2
3
5
2
0
]
D=\left[\begin{array}{cccc}0 & \text { Inf } & 3 & 3 \\ \text { Inf } & 0 & \text { Inf } & 5 \\ 3 & \text { Inf } & 0 & 2 \\ 3 & 5 & 2 & 0\end{array}\right]
D=⎣⎢⎢⎡0 Inf 33 Inf 0 Inf 53 Inf 023520⎦⎥⎥⎤
(1)无向图对应的权重邻接矩阵D是一个对称矩阵;
(2)其主对角线上元素为0.
(3)
𝐷
i
𝐷_i
Di
j
_j
j 表示第i个节点到第j个节点的权重。
2.有向图的权重邻接矩阵
则:
D
=
[
0
Inf
8
3
Inf
0
Inf
5
8
Inf
0
2
Inf
Inf
Inf
0
]
D=\left[\begin{array}{cccc}0 & \text { Inf } & 8 & 3 \\ \text { Inf } & 0 & \text { Inf } & 5 \\ 8 & \text { Inf } & 0 & 2 \\ \text { Inf } & \text { Inf } & \text { Inf } & 0\end{array}\right]
D=⎣⎢⎢⎡0 Inf 8 Inf Inf 0 Inf Inf 8 Inf 0 Inf 3520⎦⎥⎥⎤
(1)有向图对应的权重邻接矩阵D是一般不再是对称矩阵;
(2)其主对角线上元素为0.
(3)
𝐷
i
𝐷_i
Di
j
_j
j 表示第i个节点到第j个节点的权重。
相关算法
1.迪杰斯特拉算法
清风老师推荐的学习视频,里面讲的很清楚易懂:
https://www.bilibili.com/video/av54668527
- 迪杰斯特拉算法的一个缺点:可以用于有向图,但是不能处理负权重
2.Bellman‐Ford(贝尔曼‐福特)算法
可以修复上个算法的缺点。
- 事实上,贝尔曼‐福特算法不再将节点区分为是否已访问的状态,因为贝尔曼‐福特模型是利用循环来进行更新权重的,且每循环一次,贝尔曼福特算法都会更新所有的节点的信息。
- 贝尔曼‐福特算法不支持含有负权回路的图。
有兴趣的同学可以参考下面两份资料弄懂其实现原理:
https://blog.csdn.net/a8082649/article/details/81812000
https://www.bilibili.com/video/av43217121 - 什么是负权回路:
在一个图里每条边都有一个权值(有正有负)如果存在一个环(从某个点出发又回到自己的路径),而且这个环上所有权值之和是负数,那这就是一个负权环,也叫负权回路。
存在负权回路的图是不能求两点间最短路的,因为只要在负权回路上不断兜圈子,所得的最短路长度可以任意小。
如:
注意:
贝尔曼‐福特算法实际上处理的是具有负权重的有向图。(且该有向图也不能含有负权回路)
3.Floyd算法
- Floyd算法与迪杰斯特拉算法或贝尔曼福特算法相比,能够一次性的求出任意两点之间的最短路径,后两种算法运行一次只能计算出给定的起点和终点之间的最短路径。可以正确处理无向图或有向图(可以有负权重,但不可存在
负权回路)。 - 本质是三层循环
参考:https://www.bilibili.com/video/av54668527 后半段视频
Matlab代码
1.Matlab作图:
% 函数graph(s,t):可在 s 和 t 中的对应节点之间创建边,并生成一个图
G1 = graph(s1, t1);
plot(G1)
% 函数graph(s,t,w):可在 s 和 t 中的对应节点之间以w的权重创建边,并生成一个图
G2 = graph(s2, t2);
plot(G2, 'linewidth', 2) %设置线的宽度
% 下面的命令是在画图后不显示坐标
set( gca, 'XTick', [], 'YTick', [] );
%上面都是无向图
%要做出有向图,只需要将graph改为digraph就行了
如果节点比较少,推荐使用在线网站作图
该函数在2015b之后的版本才支持,如果运行出错请下载新版本Matlab。
2.Matlab计算最短路径
[P,d] = shortestpath(G,start,end [,'Method',algorithm] )
% 功能:返回图G中start节点到end节点的最短路径
输入参数:
(1)G ‐ 输入图(graph 对象 | digraph 对象)
(2)start 起始的节点
(3)end 目标的节点
(4)[,‘Method’,algorithm] 是可选的参数,表示计算最短路径的算法。一般我们不用手动设置,默认使用的是“auto”。
输出参数:
(1)P – 最短路径经过的节点
(2)d – 最短距离
该函数在2015b之后的版本才支持,如果运行出错请下载新版本Matlab。
3.返回任意两点的距离矩阵:
d = distances(G [,'Method',algorithm])
4.找给定范围的所有的点
[nodeIDs,dist] = nearest(G,s,d [,'Method',algorithm])
返回图形 G 中与节点 s 的距离在 d 之内的所有节点。
nodeIDs是符合条件的节点
dist是这些节点与s的距离