zoukankan      html  css  js  c++  java
  • DFS搜索算法--(1)基础图遍历 绝对看!的!懂!

    内容总结 自《啊哈!算法!》

    作为一个都大二的了一个菜鸡,做题的时候DFS怎么可以不会呢!!!

    作为一个都大二了的(!!!)菜鸡....《啊哈算法》这本书第四章的搜索,开始那里我就没看懂,就跑来看第五章了。结果这个理解起来方便一些....总结摘抄一下给远方的不知名网友and for myself。

    以下语言有不严谨之处请多包涵,先理解重要。

    深度搜索算法,就是对于一个图(图自己瞎画的  太丑)  如下图所示,给这些圆圈标号。

    然后我们遍历的时候,是“优先深度” ,先从一条路走到黑走不动了再换条道继续一条路走到黑。即先从1开始,走到2,走到5. 然后走不动了就先回去,先回到2,发现还有6可以走,然后又走到6了。然后又走不动了。便回到2,但是2的所有支路已经都被访问过了,那就再往回走一个,走到1。 回到1以后,2这条道已经走完了,就走到3,再走到7,走不动了再回到3,3没有别的支路可以走了就再回到1,然后再走4

    那么上图的访问顺序是(不算重复的顶点):1  2  5  6  3  7  4

    如果一条道走完了,比如说从2走到5,走完了,就要回到上一个路口顶点2。从5到2的过程称为回溯。

    那么如何存储一个图呢?我们用一个二维数组arr来存储:

    如上两个图所示,二维数组中第i行第j列表示的就是顶点i到顶点j是否有边。1表示有边,空着的就是没有边(在编程时可以将其赋值为9999,画图太麻烦我就省去了) ,二维数组行和列相等的我赋值为0.

    能看到,上面的这个图是关于主对角线对称的,这是因为这个图是个‘无向图’。也就是这个图的边没有方向,从1到2和从2到1是一样的,所以 arr[ 2 ] [ 1 ] = arr[ 1 ][ 2 ] = 1。

    以下是代码实现:

    其中,book[  ]  这个数组一开始全部赋初值为0,表示未被访问过。被访问赋值为1。

    还有一个需要知道的小知识点,就是我的代码内又两个return,第一个return表示函数结束,第二个return表示返回上一个dfs()函数,这是递归函数的特殊用法。比如:现在是dfs(5),执行代码时遇到了代码中第二个return,然后就会返回上一个执行的dfs()函数,这就变成了dfs(2),这个过程就是回溯。

     1 void dfs(int cur)//cur是当前在的顶点的编号
     2 {
     3     printf("%d ",cur);//按顺序打印出遍历过的点
     4     sum++;//sum是全局变量,初值为0。每访问一个点,sum++。
     5     if(sum==n)
     6         return ;//n为全局变量,是总共点的数量。若sum==n,便是点都访问完了,就退出函数。
     7     
     8     for(int i=1;i<=n;i++)//从1号点到n号点依次尝试,看看谁与cur点相连着
     9     {
    10         if(arr[cur][i]==1&&book[i]==0)//若这个点没有被访问过并且与cur相连
    11         {
    12             book[i]=1;//把这个点标记为已访问
    13             dfs(i);//递归,继续从这个点再继续深入遍历
    14         }
    15     }
    16     return ;//当与cur相连的所有点都已被访问过了,就返回到上一个dfs()
    17 }

    完整代码如下:

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 
     5 int book[101],sum,n,arr[101][101];
     6 
     7 void dfs(int cur)//cur是当前在的顶点的编号
     8 {
     9     printf("%d ",cur);//按顺序打印出遍历过的点
    10     sum++;//sum是全局变量,初值为0。每访问一个点,sum++。
    11     if(sum==n)
    12         return ;//n为全局变量,是总共点的数量。若sum==n,便是点都访问完了,就退出函数。
    13 
    14     for(int i=1;i<=n;i++)//从1号点到n号点依次尝试,看看谁与cur点相连着
    15     {
    16         if(arr[cur][i]==1&&book[i]==0)//若这个点没有被访问过并且与cur相连
    17         {
    18             book[i]=1;//把这个点标记为已访问
    19             dfs(i);//递归,继续从这个点再继续深入遍历
    20         }
    21     }
    22     return ;//当与cur相连的所有点都已被访问过了,就返回到上一个dfs()
    23 }
    24 
    25 
    26 
    27 int main()
    28 {
    29     sum=0;
    30     int m,a,b;
    31     cin>>n>>m;//m表示有几条边  n表示有几个点
    32     for(int i=1;i<=n;i++){
    33         for(int j=1;j<=n;j++){
    34             if(i==j)
    35                 arr[i][j]=0;
    36             else
    37                 arr[i][j]=9999999;//把没有边相连的标记为999999
    38         }
    39     }
    40 
    41     //读入顶点之间的那些边
    42     for(int i=0;i<m;i++)
    43     {
    44         cin>>a>>b;
    45         arr[a][b]=1;
    46         arr[b][a]=1;//由于时无向图,所以两个都要标记。在前面我说过了
    47     }
    48     book[1]=1;//从1号顶点出发。标记1号顶点已经被访问
    49     dfs(1);
    50 
    51     getchar();getchar();
    52 
    53 
    54     return 0;
    55 }

    ok fine 那么简单图遍历就说完了  下次继续写

  • 相关阅读:
    产品逻辑中的—B端技术常识:同步异步接口模式
    高德地图0907
    高德地图出异常
    svn提交报错
    高德地图demo
    JS中一些特殊的方法
    video标签的学习
    document.getElementById('file').files[0]的jquery写法
    layer请求设置遮罩
    easypoi入门<1
  • 原文地址:https://www.cnblogs.com/juzijuziju/p/11461471.html
Copyright © 2011-2022 走看看