一、图的存储
对于图有两种存储方式。
邻接表:倾向于稀疏图(边的条数远远小于
的图)时选择。存储空间:
。
邻接矩阵:倾向于稠密图(边的条数接近
的图)时选择。存储空间:
。
邻接链表无法快速判断一条边是否是图中的一条边,邻接矩阵则可以,但是邻接矩阵存储空间消耗更高。
有向图的转置操作:的转置图
,是将图
的所有边方向反过来。
(1)若图以邻接表形式存储,时间复杂度:。
(2)若图以邻接矩阵形式存储,时间复杂度:。
二、广度优先搜索(BFS)
1、BFS算法介绍
Prim的最小生成树算法和Dijkstra的单源最短路径算法都使用了类似广度优先搜索的思想。给定图和一个可识别源结点
,BFS可以计算从源结点到每个可到达的结点的距离(最少的边数),同时生成一棵广度优先搜索树。在广度优先搜索树里从结点
到结点
的简单路径所对应的就是图
中从结点
到结点
的最短路径,即包含最少边数的路径。该算法总是在发现所有距离源结点
为
的所有结点后才会发现距离源结点
为
的其他结点。
染色:在广度优先搜索过程中,在概念上将每个结点涂上白色、灰色或黑色。所有结点一开始均涂上白色。在算法运行过程中,结点被发现则颜色会发生改变。如果边中,结点
是黑色,则
不是黑色就是灰色。也即,与黑色结点邻接的结点都已被发现。对于灰色结点来说,其邻接结点中可能存在未被发现的白色结点。灰色结点所代表的就是已知和未知两个集合的边界。
下面给出BFS在邻接表中的算法伪代码(我们将每个结点的颜色存放在属性
中,将
的前驱结点/父结点存放在属性
中(记录路径),将BFS计算出的从源结点
到
的距离存放在属性
中,若
从
不可达,则
。该算法用队列
存放灰色结点):
BFS(
,
)
1 for each vertex
2
WHITE
3
4
NIL
5
GRAY
6
7
NIL
8
9 ENQUEUE(
)
10 while
11
DEQUEUE(
)
12 for each
13 if
WHITE
14
GRAY
15
16
17 ENQUEUE(
)
18
BLACK
解释:1至8行进行初始化,第9行将源结点入队(ENQUEUE为入队操作);10至18行进行while循环直至队列为空(无灰色结点)。该循环不断从队列中取出结点
(DEQUEUE出队操作),检查其邻接结点集合
。若其邻接结点
为白色(未被发现),则涂灰,其距离属性
为
,
的父结点为
,将
入队。直到
的所有邻接节点都被发现,则其颜色标位黑色。
举例:
时间复杂度:邻接表存储:;邻接矩阵存储:
。
分析(采用聚合分析):初始化操作,每个结点入队出队最多一次,故入队出队操作总代价
,for循环的总次数不超过边数(但是这里需要注意,对于不同的存储方式,遍历邻接边的代价不同,邻接表为
,邻接矩阵为
)。则对于图的邻接表存储,广度优先搜索的代价为
;对于邻接矩阵为
。
2、引理和推论
下面我们将给出证明BFS正确性的一些引理和推论:
引理2.1:给定