BFS和DFS主要用于连通图遍历,应用广泛,且模版性强,可举一反三

BFS主要应用于连通图的遍历,它的核心思想是从一个顶点开始,辐射状地优先遍历其周围较广的区域,即逐层遍历,BFS最经典的应用场景为最短路径,很多最短路径算法都是基于BFS实现,BFS通常基于队列的思想实现,其实现过程如下:

      (1)顶点入队列

      (2)队列为空,算法结束,队列非空,算法继续执行

      (3)出队列取得队头元素

      (4)查找队头元素所有子节点,未遍历则依次入队

      (5)转步骤2

/* BFS 伪代码 */
bool BFS(Node n){
  Queue q; //定义队列
  q.push(n);    //顶点节点入栈
  visit(n);
  while(!q.empty()) {
    Node front = q.front();
    if (check(front)) {
      return true;    //检查节点状态是否为目标状态
    }
    q.pop();    //队首出队
    for (Node x in front) {    //遍历当前节点的邻节点
      if (!visited(x)) {
        q.push(x);    //为访问的节点进入队列
        visit(x);    //标记当前节点已访问
      }
    }
  }
  return false;
}

深度优先搜索DFS(Depth First Search)主要应用于连通图的遍历,是从初始结点开始扩展,扩展顺序总是先扩展最新产生的结点。这就使得搜索沿着状态空间某条单一的路径进行下去,直到最后的结点不能产生新结点或者找到目标结点为止。当搜索到不能产生新的结点的时候,就沿着结点产生顺序的反方向寻找可以产生新结点的结点,并扩展它,形成另一条搜索路径。

为了便于进行搜索,要设置一个表存储所有的结点。由于在深度优先搜索算法中,要满足先生成的结点后扩展的原则,所以存储结点的表一般采用栈这种数据结构。

  深度优先搜索算法的搜索步骤一般是:

      (1)从初始结点开始,将待扩展结点依次放到栈中。

      (2)如果栈空,即所有待扩展结点已全部扩展完毕,则问题无解,退出。

      (3)取栈中最新加入的结点,即栈顶结点出栈,并用相应的扩展原则扩展出所有的子结点,并按顺序将这些结点放入栈中。若没有子结点产生,则转(2)。

      (4)如果某个子结点为目标结点,则找到问题的解(这不一定是最优解),结束。如果要求得问题的最优解,或者所有解,则转(2),继续搜索新的目标结点。

/* DFS 伪代码 */
//递归版
bool DFS(Node n){
  if (check(n)) {
    return true;    //检查节点状态是否为目标状态
  }

  for (Node x in n) {    //    遍历n相邻节点
    if (!visited(x)) {    //跳过已遍历的节点
      visit(x);    //标记当前节点已访问
      if (DFS(x)) { //判断是否搜索出解
        return true;
      }
      unvisit(x);    //若要遍历所有路径,需要重置节点状态,若只需遍历所有节点,则不需要重置节点状态
    }
  }

  return false;    //本次搜索无解
}

//非递归版
bool DFS(Node n){
  Stack s;    //

  s.push(n);
  while (!s.empty()) {
    if (visited(s.top())) {    
      unvisit(s.top());    //若要遍历所有路径,需要重置节点状态,若只需遍历所有节点,则不需要重置节点状态
      s.pop();    //跳过已遍历的节点
      continue;
    }

    if (check(s.top())) {
      return true;    //检查节点状态是否为目标状态
    }

    visit(s.top());    //标记当前节点已访问
    for (Node x in n) {    //    遍历n相邻节点
      if (!visited(x))
        s.push(x);    //将访问的节点进栈
    }
  }

  return false;    //搜索无解
}

//上下左右方向遍历
const int dir[5] = {0, 1, 0, -1, 0};
for (int i = 0; i < 4; i++) {
x = x + dir[i];
y = y + dir[i + 1];
}