DFS

一、DFS介绍

    深度优先搜索算法(英语:Depth-First-Search,简称DFS)是一种用于遍历或搜索树或图的算法。沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。属于盲目搜索。

    深度优先搜索是图论中的经典算法,利用深度优先搜索算法可以产生目标图的相应拓扑排序表,利用拓扑排序表可以方便的解决很多相关的图论问题,如最大路径问题等等。

1.1 主要思想

主要思想:不撞南墙不回头。

深度优先遍历的主要思想就是:首先以一个未被访问过的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点;当没有未访问过的顶点时,则回到上一个顶点,继续试探访问别的顶点,直到所有的顶点都被访问。沿着某条路径遍历直到末端,然后回溯,再沿着另一条进行同样的遍历,直到所有的顶点都被访问过为止。

1.2 伪代码

 void dfs()  
 {  
     // 判断是否到达终点
      if() {
          return;
      }
  
     // 尝试每一个可走方向(右下左上) 
      for(i=0; i<n; i++){ 
         // 判断是否可走,可走调用递归尝试下一步,不可走则尝试该点的其他方向
         if () {
             // 继续下一步  
             dfs();  
         }
     }  
 }

1.3 C++代码

   public void DFS( int x, int y )
          throws Exception
      {
  
          int tx, ty;
  
          int[] pos =
              { x, y };
          dfs_posList.add(pos);
 
         // 是否到达目的地
         if (mMapView[y][x] == 8)
         {
             throw new Exception("find");
         }
 
         // 顺时针循环,右下左上四个方向
         for (int k = 0; k < 4; k++)
         {
             tx = x + next[k][1];
             ty = y + next[k][0];
 
             // 是否出了边界
             boolean isOut = tx < 0 || tx >= mapWidth || ty < 0 || ty >= mapHeight;
             if (!isOut)
             {
 
                 // 是否是障碍物
                 if (mMapView[ty][tx] == 0 && dfs_book[tx][ty] == 0 || mMapView[ty][tx] == 8)
                 {
                     dfs_book[tx][ty] = 1;
                     DFS(tx, ty);
                     dfs_book[tx][ty] = 0;
                 }
             }
 
         }
     }

// 判断方向的数组 int[][] next =

       {
               { 0, 1 }, // 右
               { 1, 0 }, // 下
               { 0, -1 }, // 左
               { -1, 0 } // 上
       };

二、实现方法

1. 首先将根节点放入队列中。

2. 从队列中取出第一个节点,并检验它是否为目标。

   如果找到目标,则结束搜寻并回传结果。

   否则将它某一个尚未检验过的直接子节点加入队列中。

3. 重复步骤2。

4. 如果不存在未检测过的直接子节点。

   将上一级节点加入队列中。

   重复步骤2。

5. 重复步骤4。

6. 若队列为空,表示整张图都检查过了——亦即图中没有欲搜寻的目标。结束搜寻并回传“找不到目标”。

C++的实现

定义一个结构体来表达一个二叉树的节点的结构:

1 struct Node {
2     int self;     // 数据
3     Node *left;   // 左节点
4     Node *right;  // 右节点
5 };

那么我们在搜索一个树的时候,从一个节点开始,能首先获取的是它的两个子节点。例如:

 
                 A
           B           C
      D   E          F   G
                                      
 

A是第一个访问的,然后顺序是B和D、然后是E。然后再是C、F、G。那么我们怎么来保证这个顺序呢?

这里就应该用堆栈的结构,因为堆栈是一个先进后出的顺序。通过使用C++STL,下面的程序能帮助理解:

   const int TREE_SIZE = 9;
 3 std::stack<Node *> unvisited;
 4 Node nodes[TREE_SIZE];
 5 Node *current;
 6 
 7 //初始化树
 8 for (int i = 0; i < TREE_SIZE; i++) {
 9     nodes[i].self = i;
10     int child = i * 2 + 1;
11     if (child < TREE_SIZE) // Left child
12         nodes[i].left = &nodes[child];
13     else
14         nodes[i].left = NULL;
15     child++;
16     if (child < TREE_SIZE) // Right child
17         nodes[i].right = &nodes[child];
18     else
19         nodes[i].right = NULL;
20 }
21 
22 unvisited.push(&nodes[0]); //先把0放入UNVISITED stack
23 
24 // 只有UNVISITED不空
25 while (!unvisited.empty()) {
26     current = (unvisited.top()); //当前应该访问的
27     unvisited.pop();
28     if (current->right != NULL)
29         unvisited.push(current->right); // 把右边压入 因为右边的访问次序是在左边之后
30     if (current->left != NULL)
31         unvisited.push(current->left);
32     cout << current->self << endl;
33 }

参考: http://blog.csdn.net/g11d111/article/details/75645970



  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值