图是一种网状数据结构,是由非空的顶点集合和一个描述顶点之间关系的集合组成,它是多对多的关系。
图的形式化定义如下:
图是由(V, E)来表示的,对于无向图来说,其中 V = (v0, v1, … , vn),E = { (vi,vj) (0 <= i, j <= n且i 不等于j)},对于有向图,E = { < vi,vj > (0 <= i, j <= n且i 不等于j)}。
V是具有相同特性的数据元素的集合,V中的数据元素通常被称为顶点。
E是两个顶点之间的关系的集合,也就是边的集合
若
若
在无向图和有向图中V中的元素称为顶点,而顶点之间的关系称为弧或边,在不影响理解的情况下,我们接下来将它们称为边。
并且顶点和边的数量都是有限的,我们记为|V|和|E|。
无向图其实也是有向图,它是双向图。
加权图:
比如上图所示,每条边上面的数字既可以代表距离,也可以代表时间。具体代表什么要看当用它的时候代表的实际意义。
但是在正常的生活中,当我们使用图的时候,图是如何存储的呢。
邻接表: 链表 -> 链式存储结构
链式存储的方式从图中可以看出是使用了数组和链表的方式。
图的遍历就是从某个顶点出发,按照某种方法对图中的所有顶点访问且访问一次。
图的遍历算法是求解图的连通性问题、拓扑排序和求关键路径等算法的基础。
eg1:
无向图的深度优先遍历:0->1->3->7->4->2->5->6
无向图的广度优先遍历:0->1->2->3->4->5->6->7
eg2:
无向图的深度优先遍历:a b c e f d g h i
无向图的广度优先遍历:a b c d e f g h i
(答案并不是唯一的,前面讲过在实际应用场景,图的存储方式使用链式存储方式较多,所以在遍历的过程中要看你是如何存储数据的,再得出相应的遍历顺序)
问题:计算v1->v8的距离是多少?
解1:段数最少的最短路径
如:所经历的边或弧最少的路径(拿坐地铁来说就是换乘最少)
解决方法:广度优先搜索,和权值无关,需要借助队列来实现
对于已经检查的顶点标记为已检查,否则会出现无限循环,可以新创建一个列表用于存储已经检查的顶点,找到目标顶点则结束。第一次找到就是跳转最少的路径。如果最后队列为空,就说明没有路径可以到达目标顶点。
新建两个队列S T
解2:权值最小的路径
eg:时间最少,距离最少
解决方法:狄克斯特拉算法
我们创建两个数组
数组S:v1
数组T:v2 v3 v4 v5 v6 v7 v8
创建一个表格(-1表示无穷)
前一个结点 | 当前结点 | 权值 |
---|---|---|
v1 | v2 | -1(3) |
v1 | v3 | -1(5) |
v1 | v4 | -1(6) |
v5 | -1 | |
v6 | -1 | |
v7 | -1 | |
v8 | -1 |
表示的是从v1开始,它可以通向的结点是v2 v3 v4,并且权值分别是3 5 6。比无穷大要小,所以替换掉-1。
下一步把v2取出来
数组S:v1 v2
数组T:v3 v4 v5 v6 v7 v8
前一个结点 | 当前结点 | 权值 |
---|---|---|
v1 | v2 | 3 |
v2 | v3 | 5 (1 + 3) |
v1 | v4 | 6 |
v2 | v5 | -1(7+3) |
v2 | v6 | -1(4+3) |
v7 | -1 | |
v8 | -1 |
可以看出v2可以通向的结点是v3 v5 v6,权值分别是1 7 4。我们已知从v1 -> v3的权值是5,v1->v2的权值是3,v2->v3的权值是1,可以得出v1->v2->v3的权值是1 + 3 =4,小于从v1->v3的权值5。所以用1+3替换掉5.同理v5 v6的权值是7+3和4+3
得出新表
前一个结点 | 当前结点 | 权值 |
---|---|---|
v1 | v2 | 3 |
v2 | v3 | 4 |
v1 | v4 | 6 |
v2 | v5 | 10 |
v2 | v6 | 7 |
v7 | -1 | |
v8 | -1 |
接下来看v3可以通向的结点是v4 v6,权值分别是1 2。
数组S:v1 v2 v3
数组T:v4 v5 v6 v7 v8
前一个结点 | 当前结点 | 权值 |
---|---|---|
v1 | v2 | 3 |
v2 | v3 | 4 |
v3 | v4 | 6(1 + 4) |
v2 | v5 | 10 |
v3 | v6 | 7(2 + 4) |
v7 | -1 | |
v8 | -1 |
同理得出新表
前一个结点 | 当前结点 | 权值 |
---|---|---|
v1 | v2 | 3 |
v2 | v3 | 4 |
v3 | v4 | 5 |
v2 | v5 | 10 |
v3 | v6 | 6 |
v7 | -1 | |
v8 | -1 |
接下来看V4
数组S:v1 v2 v3 v4
数组T:v5 v6 v7 v8
v4可以通向的结点有v6和v7,权值分别是3 5
前一个结点 | 当前结点 | 权值 |
---|---|---|
v1 | v2 | 3 |
v2 | v3 | 4 |
v3 | v4 | 5 |
v2 | v5 | 10 |
v3(v4) | v6 | 6(3+5) |
v4 | v7 | -1(5) |
v8 | -1 |
可以看出,当v6的上一个结点是v4的时候,它的最小权值是8,当v6的上一个结点是v3的时候,它的最小权值是6,所以这里不做替换。得出新表
前一个结点 | 当前结点 | 权值 |
---|---|---|
v1 | v2 | 3 |
v2 | v3 | 4 |
v3 | v4 | 5 |
v2 | v5 | 10 |
v3 | v6 | 6 |
v4 | v7 | 5 |
v8 | -1 |
以此类推到最后的结果是:
前一个结点 | 当前结点 | 权值 |
---|---|---|
v1 | v2 | 3 |
v2 | v3 | 4 |
v3 | v4 | 5 |
v6 | v5 | 8 |
v3 | v6 | 6 |
v6 | v7 | 7 |
v7 | v8 | 12 |
最后可以得出从v1到v8的最小权值的路线是
v1->v2->v3->v6->v7->v8,权值为12。
图的应用在实际开发中,用的很少。但是它用到的数据结构和hashMap等数据结构有些相似的地方,用作了解吧。
本博客文章皆出于学习目的,个人总结或摘抄整理自网络。引用参考部分在文章中都有原文链接,如疏忽未给出请联系本人。另外,如文章内容有错误,欢迎各方大神指导交流。