图的遍历:广度优先遍历(BFS)

1.与树的广度优先遍历之间的联系

先回顾一下树的广度优先遍历也就是层序遍历。

1.树的广度优先遍历(队列)

  1. 若树非空,则根节点入队。
  2. 若队列非空,队头元素出队并访问,同时将该元素的孩子依次入队。
  3. 重复②直到队列为空。

2.图的广度优先遍历

  1. 找到与一个顶点相邻的所有顶点。
  2. 标记哪些顶点被访问过。
  3. 需要一个辅助队列。

注意:这里需要使用要: 图的基本操作中的查找邻接点和查找下一个邻接点的操作。

定义一个标记数组,记录每个顶点是否被访问过。

代码实现:

bool visited[MAX_VERTEX_NUM];//访问标记数组

//广度优先遍历
void BFS(Graph G, int v) {//从顶点v出发,广度优先遍历图G
    visit(v);//访问初始顶点v
    visited[v] = TRUE;//对v做已访问标记
    Enqueue(Q, v);//顶点v入队列Q
    while (!isEmpty(Q)) {
        DeQueue(Q, v);//顶点v出队列
        for (w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w))
            //检测v所有邻接点
            if (!visited[w]) {//w为v的尚未访问的邻接顶点
                visit(w);//访问顶点w
                visited[w] = TRUE;//对w做已访问标记
                EnQueue(Q, w);//顶点w入队列
            }//if
    }// while
}

2.算法分析

值得一提的是:

  • 同一个图的邻接矩阵表示方式唯一,因此广度优先遍历序列唯一。
  • 同一个图邻接表表示方式不唯一,因此广度优先遍历序列不唯一。

如果采用上述算法,若是图是非连通图,则无法遍历完所有结点。
解决方法:遍历完一轮后,重新访问标记数组,找到依旧为false的结点,再调用一次BFS。

修改后代码为:

bool visited[MAX_VERTEX_NUM];//访问标记数组

void BFSTraverse(Graph G) {//对图G进行广度优先遍历
    for (i = 0; i < G.vexnum; ++i)
        visited[i] = FALSE;//访问标记数组初始化
    InitQueue(Q);//初始化辅助队列Q
    for (i =; i < G.vexnum; ++i)//从0号顶点开始遍历
        if (!visited[i])//对每个连通分量调用一次BFS
            BFS(G, i);
    // vi未访问过,从vi开始BFS
}

//广度优先遍历
void BFS(Graph G, int v) {//从顶点v出发,广度优先遍历图G
    visit(v);//访问初始顶点v
    visited[v] = TRUE;//对v做已访问标记
    Enqueue(Q, v);//顶点v入队列Q
    while (!isEmpty(Q)) {
        DeQueue(Q, v);//顶点v出队列
        for (w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w))
            //检测v所有邻接点
            if (!visited[w]) {//w为v的尚未访问的邻接顶点
                visit(w);//访问顶点w
                visited[w] = TRUE;//对w做已访问标记
                EnQueue(Q, w);//顶点w入队列
            }//if
    }// while
}

结论:对于无向图,调用BFS函数的次数=连通分量数.

3.复杂度分析

1.空间复杂度

最坏情况,辅助队列大小为O(IV|).

2.时间复杂度

  • 邻接矩阵存储的图:访问个顶点需要OI)的时间,查找每个顶点的邻接点都需要O()的时间,而总共有||个顶点时间复杂度= O(IV|2)。
  • 邻接表存储的图:访问个顶点需要O(V)的时间,查找各个顶点的邻接点共需要O(E)的时间,时间复杂度为O(|V|+|E|).

4.广度优先生成树

在广度优先遍历的过程中,将所有结点时经过的路径连上就是一颗生成树。

广度优先生成树由广度优先遍历过程确定。
由于邻接表的表示方式不唯一,因此基于邻接表的广度优先生成树,也不唯一。

对非连通图的广度优先遍历,可得到广度优先生成森林。

你可能感兴趣的:(数据结构与算法,图论,算法,数据结构)