广度优先遍历(BFS)

树的遍历:不存在“回路”,搜索相邻的结点时,不可能搜到已经访问过的结点
图的遍历:搜索相邻的顶点时,有可能搜到已经访问过的顶点
要点:

  1. 找到与一个顶点相邻的所有顶点
  2. 标记哪些顶点被访问过
  3. 需要一个辅助队列
  • FirstNeighbor(G,x):求图G中顶点x的第一个邻接点,若有则返回顶点号,若x没有邻接点或图中不存在x,则返回-1
  • NextNeighbor(G,x,y):假设图G中顶点y是顶点x的一个邻接点,返回除y之外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1

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

bool visited[MAX_VERTEX_NUM]; //访问标记数组
//广度优先遍历
void BFS(Grapg 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算法(Final版)

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=0;i<G.vexnum;++i)	//从0号顶点开始遍历
        if(!visited[i])		//对每个连通分量调用一次BFS
            BFS(G,i);		//vi未访问过,从vi开始BFS
}
//广度优先遍历
void BFS(Grapg 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函数的次数=连通分量数

广度优先生成树

数据结构-图的遍历_广度优先

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

广度优先生成森林

数据结构-图的遍历_算法_02

深度优先遍历(DFS)

bool visited[MAX_VERTEX_NUM];
void DFS(Graph G,int v){	//从顶点v出发,深度优先遍历图G
	visit(v);				//访问顶点v
    visited[v]=TRUE;		//设已访问标记
    for(w=FirstNeighbor(G,v);w>=0;w=NextNeighor(G,v,w))
        if(!visited[w]){	//w为u的尚未访问的邻接顶点
            DFS(G,w);
        }//if
}

数据结构-图的遍历_数据结构_03


DFS算法(Final版)

bool visited[MAX_VERTEX_NUM]	//访问标记数组
void DFSTraverse(Graph G){		//对图G进行深度优先遍历
	for(v=0;v<G.vexnum;++v)
    	visited[v]=FALSE;		//初始化已访问标记数据
	for(v=0;v<G.vexnum;++v)		//本代码中是从v=0开始遍历
    	if(!visited[v])
        	DFS(G,v);
}
void DFS(Graph G,int v){	//从顶点v出发,深度优先遍历图G
	visit(v);				//访问顶点v
    visited[v]=TRUE;		//设已访问标记
    for(w=FirstNeighbor(G,v);w>=0;w=NextNeighor(G,v,w))
        if(!visited[w]){	//w为u的尚未访问的邻接顶点
            DFS(G,w);
        }//if
}

解决非连通图

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

图的遍历与图的连通性

对无向图进行BFS/DFS遍历
调用BFS/DFS函数的次数=连通分量数
对于连通图,只需调用1次BFS/DFS

对有向图进行BFS/DFS遍历
调用BFS/DFS函数的次数要具体问题具体分析
若起始顶点到其他各顶点都有路径,则只需调用1次
BFS/DFS函数

对于强连通图,从任一结点出发都只需调用1次BFS/DFS