数据结构——图的广度优先遍历(BFS)

——本节内容为Bilibili王道考研《数据结构》P59视频内容笔记。


目录

一、与树的广度优先遍历之间的联系

1.树的广度优先遍历(层次遍历)

(1)算法步骤

(2)算法演示

(3)特点

 2.图的广度优先遍历

(1)算法思想

(2)特点

(3)算法步骤

二、BFS算法

1.代码实现

2.代码解释

(1)BFS函数

(2)BFSTraverse函数

三、广度优先遍历序列

1.邻接矩阵

2.邻接表

四、复杂度分析

1.邻接矩阵

2.邻接表

五、广度优先生成树


一、与树的广度优先遍历之间的联系

1.树的广度优先遍历(层次遍历)

(1)算法步骤

        ①初始化一个辅助队列;

        ②根结点入队;

        ③若队列非空,则队头结点出队,并访问该结点,然后将其左、右子树结点插入队尾(如果有的话);

(2)算法演示

(3)特点

        不存在“回路”,搜索相邻的结点时,不可能搜到已经访问过的结点。


 2.图的广度优先遍历

(1)算法思想

        从指定结点出发进行访问,然后找到相邻结点进行访问,循环往复,直到访问完所有的结点;

(2)特点

        搜索相邻的结点时,有可能搜到已经访问过的结点;

(3)算法步骤

        ①找到与一个顶点相邻的所有顶点(用FirstNeighbor(G,x)NextNeighbor(G,x,y)两个基本操作来实现);

        ②标记哪些顶点被访问过(定义bool型数组:bool visited[MAX_VERTEX_NUM];来标记每个顶点有没有被访问过);

        ③需要一个辅助队列


二、BFS算法

1.代码实现

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

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

void BFS(MGraph 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入队列
			}
	}
}

2.代码解释

(1)BFS函数

        ①从顶点v出发,广度优先遍历图G;

        ②访问结点后标记为true;

        ③访问完毕后入队;

        ④while循环:队不空时,队头元素出队,这里注意出队操作第二个形参会接收出队元素,然后将v值进入后面的for循环来访问刚才出队的顶点相邻的顶点

        ⑤for循环:w=刚才出队元素的第一个邻接点,执行访问、标记、入队操作,然后找到下一个和刚才出队元素相邻的点,直到没有相邻的点,此时w=NextNeighbor返回的-1<0,退出for循环

        ⑥if循环:如果还没被标记为true,就进行访问、标记、入队操作。

(2)BFSTraverse函数

        ①该函数主要是用于“非连通图”的情况,因为BFS只能遍历完所有与指定结点相连通的结点;如果是非连通图,则需要判断还有没有未被标记为true的元素,对其进行BFS

        ②先初始化访问标记数组;

        ③初始化辅助队列;

        ④从1号结点开始遍历,每个连通分量(极大连通子图)调用一次BFS;

        ⑤对于无向图,调用BFS函数的次数=连通分量数


三、广度优先遍历序列

1.邻接矩阵

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

2.邻接表

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


四、复杂度分析

1.邻接矩阵

(1)访问|V|个顶点需要O(|V|)的时间;

(2)查找每个顶点的邻接点都需要O(|V|)的时间,而总共有|V|个顶点;

(3)两个加起来是O(|V|)+O(|V|^{2}),所以时间复杂度=O(|V|^{2})


2.邻接表

(1)访问|V|个顶点需要O(|V|)的时间;

(2)查找各个顶点的邻接点共需要O(|E|)的时间;

(3)所以时间复杂度=O(|V|+|E|)


五、广度优先生成树

1.每次访问邻接点时,第一次访问的结点作为孩子结点组成的树;

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

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

猜你喜欢

转载自blog.csdn.net/weixin_64084604/article/details/128346899