图论


一、什么是图?
- 图结构是一种与==树==结构有些==相似==的数据结构.
- 图论是数学的一个分支,在数学的概念上,==树是图的一种==
- 它以图为研究对象,研究==顶点==和==边==组成的图形的数学理论和方法.
- 主要研究的目的是事物之间的关系,顶点代表事物,边代表两个事物间的关系
那么,什么是图呢?
我们会发现,上面的结点(图中叫==顶点 Vertex==)之间的关系是不能使用树来表示使用几叉树都不可以模拟
,这个时候,我们就可以使用图来模拟它们。
图的特点
==一组顶点==:通常用 ==V(Vertex)==表示顶点的集合
==一组边==∶ 通常用==E(Edge)==表示边的集合
边是顶点和顶点之间的连线
边可以是==有向==的也可以是==无向==的
比如A–B,通常表示无向。A–>B,通常表示有向
二、图的概念
顶点:
- 表示图中的一个==节点==
- 比如地铁站中某个站/ 多个村庄中的某个村庄/ 互联网中的某台主机/人际关系中的人
边:
- 表示顶点和==顶点之间==的==连线==
- 比如地铁站中两个站点之间的直接连线,就是—个边
- 注意: 这里的边不要叫做路径,路径有其他的概念。
相邻顶点
- 由==一条边连接在一起的顶点==称为相邻顶点
度
- 一个顶点的度是==相邻顶点的数量==.
图一

路径
- 路径是顶点V1,V2…,Vn的一个==连续序列==。比如上图中的 0-1-5-9是一条简单的路径
- 简单路径::简单路径要求==不包含重复==的顶点.
- 回路:==第一个顶点==和==最后一个顶点相同的路径==称为回路。比如0-1-5-6-3-0
无向图:
- 所有的边都==没有方向==(边没有箭头)
- 比如 0 - 1之间有边,那么说明这条边可以保证0 -> 1,也可以保证 1 -> 0
图二

有向图:
- 图中的边是有方向的(边有箭头)
- 比如 0 -> 1,不能保证一定可以 1 -> 0,要根据方向来定
无权图:
- 图一
- 边没有携带权重(边无关长度和时间的长短)
- 边是没有任何意义
带权图:
- 图二
- 边有一定的权重。这里的权重可以是任意你希望表示的数据
- 比如距离或者花费的 时间 或者 票价.
三、图的表示
顶点的表示
- 使用==数组==来储存所有==顶点==
边的表示
1.邻接矩阵(非重点)

- 每个节点和一个整数相关联,该整数作为数组的下标值
- 用一个二维数组来表示顶点之间的连接.
- 在二维数组中,0表示没有连线,1表示有连线
- 通过二维数组,我们可以很快的找到一个顶点和哪些顶点有连线
- 另外,A-A,B-B(也就是顶点到自己的连线)通常使用O表示
2.邻接表(==重点==)

- 邻接表由图中每个顶点以及和==顶点相邻的顶点列表==组成
- 这个列表有很多中方式来存储,==数组/链表/字典(哈希表)==都可以
- 邻接表的问题
- 邻接表计算”出度”是比较简单的(出度:指向别人的数量,入度:指向自己的数量)
- 邻接表如果需要计算有向图的”λ度”,那么是一件非常麻烦的事情.
- 它必须构造一个“逆邻接表”,才能有效的计算“入度”但是开发中“出度”相对用的比较少
四、图的遍历
图的遍历思想
- 图的遍历思想和==树的遍历==思想是一样的.
- 图的遍历意味着需要将图中==毎个顶点访问一遍==,并且==不能有重复==的访问
有两种算法可以对图进行遍历
- ==广度==优先搜索( Breadth-First-search,简称==BFS==)
- ==深度==优先搜索(Depth-First-search,简称==DFS==)
- 两种遍历算法,都需要明确指定 第一个被访问的顶点
广度优先搜索的思路:
广度优先算法会从指定的第一个顶点开始遍历图,先访问其所有的相邻点,就像一次访问图的一层.
换句话说,就是先宽后深的访问顶点

广度优先搜索的实现:
- 创建一个==队列==Q
- 将V标注为被发现的(灰色),并将v将入队列Q
- 如果Q非空,执行下面的步骤:
- 将v从Q中取出队列.
- 将ν标注为被发现的灰色
- 将ν所有的未被访问过的邻接点(白色),加入到队列中
- 将v标志为黑色.
深度优先搜索的思路:
深度优先搜索算法将会从第—个指定的顶点开始遍历图,沿着路径直到这条路径最后被访问了
接着原路回退并探索条路径。

- 深度优先搜索算法的实现
广度优先搜索算法我们使用的是队列,这里可以使用栈完成,也可以使用递归.
方便代码书写,我们还是使用递归(递归本质上就是函数栈的调用)
为了记录顶点是否被访问过,我们使用三种颜色来反应它们的状态
- ==白色==:表示该顶点还==没有被访问==.
- ==灰色==:表示该顶点被访问过,但并==未被探索==过
- ==黑色==:表示该顶点被访问过且被==完全探索==过.
五、图结构的封装
属性和方法
属性:
- vertexes:所有顶点(数组)
- edges:边(字典)
方法:
- addVertex():添加顶点;
- addEdge(v1, v2):添加边, v1,v2表示顶点;
- toString():输出所有顶点
- bfs():广度优先搜索
- dfs():深度优先搜索;
具体代码:
1 | // 封装图结构 |
测试用例:
1 | const g = new Graph(); |
字典结构
1 | // 封装字典结构 |
队列结构:
1 | function Queue() { |
- Post title: 图论
- Create time: 2020-02-27 14:45:00
- Post link: 2020/02/27/图论/
- Copyright notice: All articles in this blog are licensed under BY-NC-SA unless stating additionally.
Comments