广度优先搜索和深度优先搜索

本文介绍了广度优先搜索(BFS)和深度优先搜索(DFS)两种基本的图搜索算法。详细探讨了它们的工作原理、应用场景及优缺点,并通过伪代码展示了算法实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

广度优先搜索

广度优先搜索(BFS),可以被形象地描述为“浅尝辄止”,具体一点就是每个顶点只访问它的邻接节点(如果它的邻接节点没有被访问)并且记录这个邻接节点,当访问完它的邻接节点之后就结束这个顶点的访问。

广度优先用到了“先进先出”队列,通过这个队列来存储第一次发现的节点,以便下一次的处理;而对于再次发现的节点,我们不予理会——不放入队列,因为再次发现的节点:

  1. 无非是已经处理完的了;
  2. 或者是存储在队列中尚未处理的。
《算法导论》对两种搜索都采用了很聪明的做法,用白色WHITE来标志未发现的节点,用灰色GRAY来标志第一次被发现的节点,用黑色BLACK来标志第二次被发现的节点。
于是有了:
BFS(G, s)
	for each vertex v in V[G]
		status[v] = WHITE
		/**其他初始化**/
	status[s] = GRAY	//s是源点
	queue q
	入队(q, s)
	while q非空
		t = 出队(q)
		for each vertex v in Adj[t]	//与t邻接的点
			if status[v] == WHITE	//只对未访问的操作
				status[v] = GRAY	//标记为第一次访问
				/**其他操作**/
				入队(q, v)
		status[t] = BLACK			//此点已经处理完了

导论还在上面的伪代码的“其他”中加入了访问长度和父节点的操作。此举可以算出,从源点到其他顶点路径的最少步数和它的具体路径。
关于广度优先搜索的一个简单应用:
假如有问题,每个村庄之间都通过桥来连通,先给出村庄的图,问村庄A到村庄B最少要通过多少座桥?这个问题很容易的转化为上面的BFS问题。

深度优先搜索

深度优先搜索(DFS),可以被形象地描述为“打破砂锅问到底”,具体一点就是访问一个顶点之后,我继而访问它的下一个邻接的顶点,如此往复,直到当前顶点已被访问或者它不存在邻接的顶点。

同样,《算法导论》采用了聪明的做法,用三种颜色来标记三种状态。但这三种状态不同于广度优先搜索:

  1. WHITE未访问顶点
  2. GRAY一条深度搜索路径上的顶点,即被发现时
  3. BLACK此顶点的邻接顶点被全部访问完之后——结束访问此顶点
DFS(G, s)
	for each vertex v in V[G]
		status[v] = WHITE
		/**其他初始化**/
	for each vertex v in V[G]
		if(status[v] == WHITE)
			DFS_VISIT(v)

DFS_VISIT(v)
	status[v] = GRAY
	for each vertex t in Adj(v)
		if(status[t] == WHITE)
			DFS_VISIT(t)
			/**其他操作**/
	status[v] = BLACK

通过在DFS搜索过程中给每一个顶点加时间戳,就可以实现拓扑排序了。实现拓扑排序需要:
对于每一个顶点,都有两个时间戳,分别这样定义:
  1. 在一个顶点刚被发现的时候,标记此顶点的第一个时间戳;
  2. 在结束此顶点的访问的时候,标记此顶点的第二个时间戳。时间戳可以用简单的123456来标记,只要能区分大小就行。
因此,你会发现,越早发现的点,它的第一个时间戳会越小,但是它的第二个时间戳会越大。

总结

两个算法都是O(V+E),在用到的时候适当选取。
  • 广度优先的话,占内存多,能找到最优解,必须遍历所有分支,广度优先的一个应用就是迪科斯彻单元最短路径算法
  • 深度优先的话,占内存少,能找到最优解(一定条件下),但能很快找到接近解(优点),可能不必遍历所有分支(也就是速度快),深度优先的一个应用就是连连看游戏





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值