广度优先搜索

尽管深度优先搜索具有许多重要用途,但该策略也具有不适合某些应用程序的缺点。 深度优先方法的最大问题在于它从其中一个邻居出发,在它返回该节点或者是访问其他邻居之前,它必须访问完从出发节点开始的整个路径。 如果我们尝试在一个大的图中发现两个节点之间的最短路径,则使用深度优先搜索会将我们一直带到图的远端,即使我们的的目的地离我们的出发点仅有一步之遥。
广度优先搜索(Breadth-first search BFS)算法通过按照与起始节点的接近程度来确定该访问哪个节点 来解决该问题,该节点根据沿最短可能路径的弧的数量来测量。 通过计算弧来测量距离时,每个弧构成一跳(hop)。 因此,广度优先搜索的本质是首先访问起始节点,然后是一跳之外的节点,然后是节点两跳,依此类推。

BFS过程分析

我们还是用上次的图来说明一下我们的BFS算法,并且与DFS做一个比较。

  1. 第一步是一样的,我们得选一个起始节点,所以我们选择与BFS算法一致的起点:
    数据结构——图(4)——广度优先搜索(BFS)算法思想-LMLPHP
  2. 下一阶段访问与该节点距离一跳的节点,图中我们容易看出是Dallas,Denver还有Portland三个节点:
    数据结构——图(4)——广度优先搜索(BFS)算法思想-LMLPHP
  3. 至此我们继续探索跳数为2的节点,如下:
    数据结构——图(4)——广度优先搜索(BFS)算法思想-LMLPHP
  4. 最终,我们就这样遍历完了图中所有的节点数据结构——图(4)——广度优先搜索(BFS)算法思想-LMLPHP

实现广度优先算法的最简单方法是使用队列用来存放未处理的节点。 在该过程的每个步骤中,我们将当前节点的邻居排入队列。 因为队列是按顺序处理的,所以距离起始节点一跳的所有节点将比两跳的节点在队列中更早出现。

/*
* 函数: breadthFirstSearch
* 用法: breadthFirstSearch(node);
* --------------------------------
* 从指定的节点处进行广度优先搜索.
*/
void breadthFirstSearch(Node *node) {
	Set<Node *> visited; //标记已访问的节点
	Queue<Node *> queue;//建立存储未被处理的节点
	queue.enqueue(node); //将要处理的节点放入空队列中
	while (!queue.isEmpty()) {//当队列中的节点数不为空时
		node = queue.dequeue(); //将队列中的节点从队列中移出
		if (!visited.contains(node)) {//如果该节点未被标记
			visit(node);//对节点进行相应处理
			visited.add(node);//处理完毕后标记该节点
			 //遍历该节点指向的下一条弧
			foreach (Arc *arc in node->arcs) {
			//将该弧所指的节点放入队列中
				queue.enqueue(arc->finish);
			}
		}
	}
}

同样的,利用这样的做法我们可以利用BFS来遍历下图:
数据结构——图(4)——广度优先搜索(BFS)算法思想-LMLPHP
具体的实现跟步骤分析下篇博文会进行说明。

10-05 13:17