(二) 图的遍历
1. 深度优先搜索 (Depth First Search, DFS)
[外链图片转存失败(img-MgjNKZTh-1567356455556)(C:\Users\alway\AppData\Roaming\Typora\typora-user-images\1567347155834.png)]
void DFS(Vertex v) {
visited[v] = true;
for (v的每个邻接点w) {
if(!visited[w]) {
DFS(w);
}
}
}
**注:**可用stack改递归为循环
**时间复杂度:**若有N个顶点,E条边
-
用邻接表存储图, O ( N + E ) O(N+E) O(N+E)
-
用邻接矩阵存储图, O ( N 2 ) O(N^2) O(N2)
2. 广度优先搜索 (Breadth First Search, BFS)
[外链图片转存失败(img-IjMMPRMt-1567356455557)(C:\Users\alway\AppData\Roaming\Typora\typora-user-images\1567347826519.png)]
void BFS(Vertex v) {
visited[v] = true;
Enqueue(v);
while(!isEmpty(Q)) {
v = Dequeue(Q);
for (v的每个邻接点w) {
if(!visited[w]) {
visited[w] = true;
Enqueue(w, Q);
}
}
}
}
**注:**使用队列改递归为循环
时间复杂度:(同上)
3. 图不连通
**连通:**如果从v到w存在一条(无向)路径,则称v与w是连通的
**强连通:**如果从v到w存在双向路径,则称v与w是强连通的
**路径:**v到w的路径是一系列顶点的集合,且任一对相邻顶点间都有图中的边
**回路:**起点等于终点的路径
**连通图:**图中任意两顶点均连通
连通分量:无向图的极大连通子图
-
极大顶点数:再加一个就不连通了
-
极大边数:包含子图中所有顶点相连的所有边
[外链图片转存失败(img-hftgLg0I-1567356455559)(C:\Users\alway\AppData\Roaming\Typora\typora-user-images\1567348540093.png)]
void ListComponents(Graph G) {
for (each v in G) {
if (!visited[v]) {
DFS(V);
}
}
}
**注:**每调用一次DFS(v)就把v所在的连通分量遍历了一遍,BFS同理
4. 代码实现
/* 邻接表存储的图 - DFS */
void Visit( Vertex V )
{
printf("正在访问顶点%d\n", V);
}
/* Visited[]为全局变量,已经初始化为false */
void DFS( LGraph Graph, Vertex V, void (*Visit)(Vertex) )
{ /* 以V为出发点对邻接表存储的图Graph进行DFS搜索 */
PtrToAdjVNode W;
Visit( V ); /* 访问第V个顶点 */
Visited[V] = true; /* 标记V已访问 */
for( W=Graph->G[V].FirstEdge; W; W=W->Next ) /* 对V的每个邻接点W->AdjV */
if ( !Visited[W->AdjV] ) /* 若W->AdjV未被访问 */
DFS( Graph, W->AdjV, Visit ); /* 则递归访问之 */
}
/* 邻接矩阵存储的图 - BFS */
/* IsEdge(Graph, V, W)检查<V, W>是否图Graph中的一条边,即W是否V的邻接点。 */
/* 此函数根据图的不同类型要做不同的实现,关键取决于对不存在的边的表示方法。*/
/* 例如对有权图, 如果不存在的边被初始化为INFINITY, 则函数实现如下: */
bool IsEdge( MGraph Graph, Vertex V, Vertex W )
{
return Graph->G[V][W]<INFINITY ? true : false;
}
/* Visited[]为全局变量,已经初始化为false */
void BFS ( MGraph Graph, Vertex S, void (*Visit)(Vertex) )
{ /* 以S为出发点对邻接矩阵存储的图Graph进行BFS搜索 */
Queue Q;
Vertex V, W;
Q = CreateQueue( MaxSize ); /* 创建空队列, MaxSize为外部定义的常数 */
/* 访问顶点S:此处可根据具体访问需要改写 */
Visit( S );
Visited[S] = true; /* 标记S已访问 */
AddQ(Q, S); /* S入队列 */
while ( !IsEmpty(Q) ) {
V = DeleteQ(Q); /* 弹出V */
for( W=0; W<Graph->Nv; W++ ) /* 对图中的每个顶点W */
/* 若W是V的邻接点并且未访问过 */
if ( !Visited[W] && IsEdge(Graph, V, W) ) {
/* 访问顶点W */
Visit( W );
Visited[W] = true; /* 标记W已访问 */
AddQ(Q, W); /* W入队列 */
}
} /* while结束*/
}