图的遍历
深度优先搜索(DFS)
类似树的先序遍历
void DFS( Vertex V )
{
visited[ V ] = true;
for( V 的每个邻接点 W )
if( !Visited[W])
DFS(W);
}
若有N个结点,E条边,时间复杂度是:
- 用邻接表存储图,有O(N+E)
- 用邻接矩阵存储图,有O(N^2)
广度优先搜索(BFS)
类似于层序遍历
void BFS( Vertex V )
{
visited[V] = true;
Enqueue(V,Q);
while(!IsEmpty(Q)) {
V = Dequeue(Q);
for( V 的每个邻接点 W )
if( !visited[W]) {
visited[W] = true;
Enqueue(W,Q);
}
}
}
若有N个结点,E条边,时间复杂度是:
- 用邻接表存储图,有O(N+E)
- 用邻接矩阵存储图,有O(N^2)
为什么需要两种遍历?
-
BFS:对于解决最短或最少问题特别有效,而且寻找深度小,但缺点是内存耗费量大(需要开大量的数组单元用来存储状态)。
-
DFS:对于解决遍历和求所有问题有效,对于问题搜索深度小的时候处理速度迅速,然而在深度很大的情况下效率不高
图不连通怎么办?
- 连通: 如果从v到w存在一条(无向)路径,则称v和w是连通的
- 路径:v到w的路径是一系列顶点 { V , v 1 , v 2 , . . . , v n , W } \lbrace V,v_1,v_2,...,v_n,W\rbrace {V,v1,v2,...,vn,W}的集合,其中任一对相邻的顶点间都有图中的边。路径的长度是路径中的边数(如果带权,则是所有边的权重和)。如果v到w之间的所有顶点都不同,则称为简单路径
- 回路:起点等于终点的路径
- 连通图:图中任意两顶点均联通
- 连通分量:无向图的极大连通子图
- 极大顶点数:再加一个顶点就不连通了
- 极大边数:包含子图中所有顶点相连的所有边
- 强连通:有向图中顶点V和W之间存在双向路径,则称V和W是强连通的
- 强连通图:有向图中任意两点均强连通
- 强连通分量:有向图的极大强连通子图
- 每调用一次DFS(V),就把V所在的连通分量遍历了一遍。BFS也是一样。
void ListComponents( Graph G )
{
for( each V in G ) {
if( !visited[V] ) {
DFS( V ); // or BFS( V )
}
}
}