本文的主题是图。与树相比,图是更通用的结构;事实上,可以把树看作一种特殊的图。

图可以用来表示现实世界中很多有意思的事物,包括道路系统、城市之间的航班、互
联网的连接,甚至是计算机专业的一系列必修课。

你在本章中会看到,一旦有了很好的表示方法,就可以用一些标准的图算法来解决那些看起来非常困难的问题。

尽管我们能够轻易看懂路线图并理解其中不同地点之间的关系,但是计算机并不具备这样的能力。不过,我们也可以将路线图看成是一张图,从而使计算机帮我们做一些非常有意思的事情。

用过互联网地图网站的人都知道,计算机可以帮助我们找到两地之间最短、最快、最便捷的路线。

计算机专业的学生可能会有这样的疑惑:自己需要学习哪些课程才能获得学位呢?图可以很
好地表示课程之间的依赖关系。下图展示了要在流沙学院获得计算机科学学位,所需学习课程
的先后顺序。
image.png

1. 术语及定义

在看了图的例子之后,现在来正式地定义图及其构成。从对树的学习中,我们已经知道了一些术语。

1.1 顶点

顶点又称节点,是图的基础部分。它可以有自己的名字,我们称作“键”。顶点也可以带有
附加信息,我们称作“有效载荷”。

1.2 边

边是图的另一个基础部分。两个顶点通过一条边相连,表示它们之间存在关系。

边既可以是单向的,也可以是双向的。如果图中的所有边都是单向的,我们称之为有向图。上面的图明显是一个有向图,因为必须修完某些课程后才能修后续的课程。

1.3 权重

边可以带权重,用来表示从一个顶点到另一个顶点的成本。例如在路线图中,从一个城市到
另一个城市,边的权重可以表示两个城市之间的距离。

2. 故事背景

2.1 人物

  1. 小白
  2. 大牛
  3. 新晋人物 — 出租车司机:深耕于出租车服务行业,每年数十万行程公里,资深出租车司机。

image.png

2.2 场景

我过的桥多于你走过的路

2.3 前言

图结构是一种比树结构更复杂的非线性结构。在图形结构中,任意两个结点之间都可能相关,即结点之间的邻接关系可以是任意的。

某某城市的高速公路上,一辆白色 SUV 正急速向前行驶。车里的一老一少正在畅谈。镜头拉近 —— 原来是出差归来的大牛和小白两人。

“牛哥,这两天我这儿提供的伙食还行吧。”

“不错不错,你看我这都胖两斤了。招待能不好吗。”

“那是必须的,虽然说没有能回家一趟,但是这庆功酒可不能省。毕竟这可是咱们俩第一次一块儿出差。而且取得了这么好的成果。”

“说来也是,这次的工作出奇的顺利。没想到这么快就能把客户搞定。”

“怎么说我也是公司的吉祥物啊。就这么几个小客户,小 case 啦。”

“喲,什么时候成公司的吉祥物了,我怎么不知道呢?”

“这不出差回来吗,那几个客户都让咱们解决了。而且我这是第一次出差,就取得了这么好的成果,所以大家亲切的称呼我为 – 小白吉祥。”
202111051944780.jpeg
“哈哈哈,小白吉祥,你是要笑死我,难不成你是要穿越回清朝当格格吗。”

“过分了啊牛哥,好不容易我在公司的知名度涨上去了,你可不能挖苦我。诶诶诶,司机师傅,咱们走错路了吧, 从刚才那个路口下去就到了”

“怎么可能。这条路我走了无数次,肯定是从前边下去近点儿。” 司机反驳到。

“不对不对,我每次去这儿都是从刚才那个路口下去的。肯定是那个近。” 小白心急的说道。

“那你是被坑了呗。从那里下去,最少要多5块钱的路费呢。听我的就行了。我过的桥比你走的路都多。肯定不会错的”

“好好好,那就先按照您的路线走。不过咱可说好了,如果路费真是多了,我可是不会多给的。”

“没问题,如果比你之前的路费多了,我分文不收。免费送你们过来。要是比之前少,我可是要加倍收费的”

“好,我就跟你赌这一次。不就是双倍车费吗,还是能付得起的。”

“小白啊,刚听你俩这话这会儿,我想起来一个事儿啊。咱们这几天是不是忘了点儿什么。” 大牛闪动着狡黠的目光问小白
image.png

“哦?我怎么不记得忘了什么。话说咱们这就快到地方了吧。” 小白顾左右而言他。

“别装糊涂,才这么大,记性不好可不行啊。”

“好好好,我也不装蒜了,我也知道牛哥你想问什么。放马过来吧,早死早超生,二十年后,本白还是一条好汉。”

“得了得了,说的跟要你命似的。上次咱们不是说到堆结构了吗,数据结构这块儿内容还有什么没问到的?”

“就剩下图结构了,剩下的你都问了个遍。我这左躲右躲的都没躲过你的追击。”

“既然你都知道了,那我也不废话了。来说说吧。”

“行,说就说,不过图结构可真复杂,我还真说不全。”

“说全了就不是你了。单这一种数据结构都够出好几本书的了。说基本的就行了。”

“好,那我开始了牛哥。不对的地方,您老可得提醒提醒我。”

“没问题,这都是小事儿。”

那还是先说说基本概念吧。毕竟这都是基础,如果这个都不知道,那剩下的都不用说了。

3. 图的定义

图:一种网络结构的抽象模型。是一组由边连接的顶点组成。
G = (V, E)

V:一组顶点
E: 一组边,用来连接 V 中的顶点
image.png

4. 相关概念

4.1 相邻顶点

由一条边连接在一起的顶点。

4.2 路径

是一组相邻顶点的连续序列。

4.3 环

通过某条路径可以返回到起始顶点。
image.png

4.4 有向图

图的边有方向
image.png

4.5 权

图的边存在的值成为权重:
image.png
“不错不错,概念说的都挺全的。但是只了解概念还不够。还得知道怎么表示和实现图。”

“莫着急啊牛哥,我就差一点儿就说到表示和实现了。”
05-图及其算法 - 图9
“好好好,那我就安静的听着。”

听好了啊。

3. 图结构的表示方式(邻接矩阵、邻接表、关联矩阵)

分别使用三种方式来表示下列图结构:
image.png

3.1 邻接矩阵

纵向为顶点,横向为相邻顶点。
使用二维数组存储,如果两个顶点之间存在连接,则值为 1 ,否则为 0。
会造成一定的存储资源浪费 。


一种 C D F G H 一世
一种 0 1 1 0 0 0 0 0 0
1 0 0 1 1 0 0 0 0
C 1 0 0 0 0 1 1 0 0
D 0 1 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0 0
F 0 0 1 0 0 0 0 1 0
G 0 0 1 0 0 0 0 1 0
H 0 0 0 0 0 1 1 0 0
一世 0 0 0 1 0 0 0 0 0

3.2 邻接表

是对邻接矩阵的改进,如下所示。

我们可以使用数组、链表、字典、散列表等来表示邻接表。

顶点 相邻顶点
一种 乙—丙
A — D — E
C A — F — G
D 乙——我
F C—H
G C—H
H F—G
一世 D

3.3 关联矩阵

纵向为顶点,横向为边。适用于顶点远大于边的情况。


e1 e2 e3 e4 e5 e6 e7 e8 e9
一种 1 1 0 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0
C 1 0 0 0 0 1 1 0 0
D 0 0 1 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0
F 0 0 0 0 0 1 0 1 0
G 0 0 0 0 0 0 1 0 1
H 0 0 0 0 0 0 0 1 1
一世 0 0 0 0 1 0 0 0 0

“到这里我就说完了我知道的表示图的方式,下面我来说说前端怎么创建和使用图。”

“看来你这几天的学习也没有落下,本牛很是欣慰啊。”

“这话说的,徒弟领进门,修行看个人嘛。怎么也不能拿自己的未来开玩笑不是。”
image.png
“这句话倒是说的不错,看来你已经领悟到了学习的精髓。我也不用太过担心了。”

“好了牛哥,咱们接着说?”

“嗯嗯,接着说,我看看你这学习到了哪个层次。”

4. 图的创建和使用

好,下面我就说说图的创建和使用。


不用看下面的:

4.2 图的遍历

1. 遍历方法

  1. 深度优先搜索 —> 栈
  2. 广度优先搜索 —> 队列请参考第三节栈和队列内容

    2. 辅助功能

    在遍历顶点的过程中,我们需要给每个节点定义两种状态,用来表示访问次数。每个顶点最多被访问两次。

  3. 白:未被访问

  4. 灰:被访问但是未被处理
  5. 黑:已被处理

    3. 广度优先搜索实例解析

    从第一个顶点开始遍历,访问所有相邻顶点,再访问相邻顶点的相邻顶点。直到所有顶点访问结束。

广度优先搜索图解

image.png

深度优先搜索图解

image.png