Bootstrap

图的广度优先遍历

  • 广度优先遍历(BFS)
  • 深度优先遍历(DFS)

图的广度优先遍历

广度优先遍历:通过某一个结点,找到与之相邻的结点。

树的广度优先遍历(层序遍历)联系:

树就是找孩子,图可以用之前提到的两个基本操作(FirstNeighbor和NextNeighbor)实现。

因为树不存在“回路”,所以树在搜索相邻的结点时,不可能搜到已经访问过的结点。但是图有可能出现环路,所以图在搜索相邻结点时,有可能搜到已经访问过的顶点。图需要一个标记,来记录已经访问过的顶点。

树在进行广度优先遍历(层序遍历)时,借助了一个辅助队列来实现:

1、若树非空,则根结点入队;

2、若队列非空,队头元素出队并访问,同时将该元素的孩子依次入队;

3、重复②直到队列为空。

图的广度优先遍历,也需要一个辅助队列

1、找到与一个顶点相邻的所有顶点(两个基本操作)

FirstNeighbor(G,x):求图G中顶点x的第一个邻接点,若有则返回顶点序号。若x没有邻接点或图中不存在x,则返回-1。

NextNeighbor(G,x,y):假设图G中顶点y是顶点x的一个邻接点,返回除y之外顶点x的下一个邻接点的顶点序号,若y是x的最后一个邻接点,则返回-1。

2、标记哪些顶点被访问过;

设置bool型数组visited[ ]记录访问过的数组。bool visited[MAX_VERTEX_NUM];

3、需要一个辅助队列。

【注意】:使用邻接矩阵存储的图的遍历,和使用邻接表存储的图的遍历,在第一步的实现有些区别。

代码实现如下:

bool visited[MAX_VERTEX_NUM];    //标记访问数组,初始值全部设为false

//广度优先遍历
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
}

例子:用广度优先算法遍历下图。

  一开始,visited[ ]数组的值全部为false,表示没有任何顶点被访问。

1 2 3 4 5 6 7 8
visited false flase false false false false false
;