图 (Graph)
图论是数学上的一个分支,在数学定义上,树是图的一种。而图本身是研究事务之间关系的。本文介绍关于图这种数据结构的一些背景知识、术语、种类及表示方法,为接下来的实现做好基础准备。
1. 图的故事
- 欧拉和七座桥的故事 -- 抽象化的力量:一笔画的前提是奇数结点的数目不是0个就是两个
- 欧拉开创的图论
2. 图的组成
图由顶点(V)和边(E)
组成,其中顶点表示的是事物,而边表示的则是所连接的两个事物之间的关系。
3. 图和树
- 树可以看成是特殊的图;在树中
没有环路
的出现 - 所谓环路可以理解成为从一个结点出发,在不走回头路的情况下能够重新回到起始结点的路线。
- 也就是说树不能表示
“环”
这种概念,无论用什么样的树都不可以,但是图可以
4. 图的应用
- 地铁线路网络
- 人与人之间的关系网
5. 图的种类
- 有向图:从一个结点发出的信息只能在边上以固定的方向传播,而不能反过来
- 无向图:两个结点之间信息的传播是双向的
- 无权图:图上面上的所有边都是平等的,不存在那条边比较重要的情况;边的存在只能表示某两个结点是有关系的!
- 有权图:图上的边除了能够表示两个结点之间有关系,还能表示其他含义,比如从A站点到B站点的距离或者票价。
6. 图相关术语
-
- 度:和一个结点相邻的结点的数量
-
- 路径:从一个结点到另外一个结点途经的结点形成的序列(不是唯一的!)
-
- 回路:一种特殊的路径,回路的起始结点和终止结点是相同的
-
- 出度:对于有向图来说是此节点指向其他结点的边的数目
-
- 入度:对于有向图来说是其他结点指向此节点的边的数目
7. 图的表示
- 结点的表示:可以使用数组中的元素表示
- 边如何表示?
-
- 用邻接矩阵:
- 用二维矩阵中元素的值表示,比如:matrix[0][2]=1就表示0号结点和2号结点之间是有边的;而matrix[2][3]=0就表示2号结点和3号结点之间是没有边的
- 上述用来表示图的做法成为邻接矩阵;显然邻接矩阵既可以表示有向图和无向图,也可以表示无权图和有权图(matrix[0][2]=1但是matrix[2][0]=0 或者 matrix[0][2]=1当时matrix[0][1]=3)
- 对称的邻接矩阵表示一个无向图
- 邻接矩阵的问题在于:此矩阵是一个稀疏矩阵,容易浪费大量的存储空间
-
- 用邻接表:
- 邻接表本质上是一个链表,例如:
[[1,4], [0,2], [1], [], [0]]
表示的含义就是:0号结点和1号,4号结点关联;1号结点和0号,2号关联;2号结点和1号结点关联;4号结点和0号结点关联。 - 显然,邻接表可以用来表示有向图,但是不能用来表示有权图。
- 对于邻接表来说,计算一个结点的出度是非常简单的,就是元素数组中元素的个数,比如:
[[1,4], [0,2], [1], [], [0]]
中0号结点对应的是下标为0的元素[1,4]
,有两个元素1和4,所以0结点的出度是2. - 然而,计算结点的入度是非常麻烦的,还需要单独构造一个
逆邻接表
,所以出度使用的比较少
-
8. 图数据结构中的属性和方法
- 属性:
-
- vertexes: 是一个数组,数组中的元素是顶点;
-
- adjList:是一个字典,用来存储边; 注意:这里没有用二维数组来做,而是用一维的数组存储顶点信息;用二维的字典存储边的信息。所以在此使用的是第二种图的表示方法--邻接表
-
- 方法:
-
- addVertex: 向图中增加一个顶点的方法
-
- addEdge:想图中增加一个边的方法
-
- toString:以某种规定的方式将邻接表打印出来
-
- 遍历方法:包括深度优先遍历和广度优先遍历两种方式
-