zoukankan      html  css  js  c++  java
  • 非递归DFS遍历

    • 深度优先搜索DFS

      DFS就是回溯法,用递归的方法是很自然的。那么该如何递归呢?

      简单的说就是:1、如果当前节点没有被搜索过,那么处理当前节点,并标记为搜索过;如果当前节点已经被搜索过,退出;

            2、递归遍历所有没有被搜索过的临接节点。

      注意,第一步的退出条件。递归必须有退出条件,否则会出现死循环。

      对任意节点调用上述DFS函数,将搜索到所有和该节点联通的节点。

    • 非递归方式实现DFS

      递归和栈总是联系在一起的,如果不采用递归,那么就需要自己维护一个栈。

      1、从某节点开始,入栈;

      2、当栈不为空时,循环3、4;当栈为空时,退出循环;

      3、对栈顶节点处理,标记为搜索过;注意,如果该节点的某个临接节点处理完后,会回溯到该节点,注意不要重复处理该节点。

      4、对栈顶节点,任意找一个没有搜索过的临接节点,入栈(注意只入栈一个临接节点,DFS就是找到一条路一直走下去,走不通了再回溯);如果发现该栈顶节点所有的临接节点都被搜索过,或者该节点没有临接节点,将该栈顶节点出栈。 

     

    • 实现代码

      下面是DFS的递归和非递归的代码,C实现。为了简单起见,搜索对象为下图所示的满二叉树,用数组表示。

      

      

      1 #include<stdio.h>
      2 #include<string.h>
      3 
      4 #define true 1
      5 #define false 0
      6 #define ok 0
      7 #define error -1
      8 
      9 #define MAX_LEN  20
     10 #define TREE_LEN  10
     11 
     12 typedef struct
     13 {
     14     int arr[MAX_LEN];
     15     int top;
     16 }STACK;
     17 
     18 int is_empty(STACK *s)
     19 {
     20     if(s == NULL )
     21     {
     22         printf("null param.
    ");
     23         return error;
     24     }        
     25     if(0 == s->top)
     26         return true;
     27     else
     28         return false;
     29 }
     30 
     31 int is_full(STACK *s)
     32 {
     33     if(s == NULL )
     34     {
     35         printf("null param.
    ");
     36         return error;
     37     }        
     38     if( MAX_LEN == s->top)
     39         return true;
     40     else 
     41         return false;
     42 }
     43 void push(STACK* s,int elem)
     44 {
     45     if(s == NULL )
     46     {
     47         printf("null param.
    ");
     48         return;
     49     }
     50         
     51     if(is_full(s))
     52     {
     53         printf("is full.
    ");
     54         return;
     55     }
     56 
     57     s->arr[s->top++] = elem;
     58 }
     59 
     60 void pop(STACK* s)
     61 {
     62     if(s == NULL )
     63     {
     64         printf("null param.
    ");
     65         return;
     66     }
     67         
     68     if(is_empty(s))
     69     {
     70         printf("is empty.
    ");
     71         return;
     72     }    
     73 
     74     s->arr[--s->top] = 0;
     75 }
     76 
     77 int top(STACK* s)
     78 {
     79     if(s == NULL )
     80     {
     81         printf("null param.
    ");
     82         return error;
     83     }
     84         
     85     if(is_empty(s))
     86     {
     87         printf("is full.
    ");
     88         return error;
     89     }        
     90 
     91     return s->arr[s->top-1];
     92 }
     93 
     94 void dfs(STACK* p_stack,int *p_tree,int tree_len)
     95 {
     96     int visited[tree_len];
     97     int temp = 0;
     98     int treeIndex = 0;
     99 
    100     memset(visited,0,sizeof(visited));
    101     
    102     push(p_stack,p_tree[treeIndex]);
    103     while(!is_empty(p_stack))
    104     {
    105         temp = top(p_stack);
    106 
    107         if(treeIndex < tree_len && !visited[treeIndex])
    108         {
    109             printf("%d->",temp);
    110             visited[treeIndex] = true;            
    111         }
    112 
    113         if(2*treeIndex+1 < tree_len && !visited[2*treeIndex+1])
    114         {
    115             push(p_stack,p_tree[2*treeIndex+1]);    
    116             treeIndex = 2*treeIndex+1;
    117         }
    118         else if( 2*treeIndex+2 < tree_len && !visited[2*treeIndex+2] )
    119         {
    120             push(p_stack,p_tree[2*treeIndex+2]);
    121             treeIndex = 2*treeIndex+2;
    122         }
    123         else
    124         {
    125             pop(p_stack);
    126             treeIndex = (treeIndex-1)>>1;
    127         }        
    128     }
    129     printf("
    ");
    130 }
    131 
    132 
    133 void dfs_reverse(int *p_tree,int*p_visited,int tree_len,int treeIndex)
    134 {
    135     int left,right = 0;
    136 
    137     if(treeIndex < tree_len && !p_visited[treeIndex])
    138     {
    139         printf("%d->",p_tree[treeIndex]);
    140         p_visited[treeIndex] = true;
    141 
    142         left = 2*treeIndex+1;
    143         if( left < tree_len && !p_visited[left])
    144             dfs_reverse(p_tree,p_visited,tree_len,left);
    145 
    146         right = 2*treeIndex+2;
    147         if( right < tree_len && !p_visited[right])
    148             dfs_reverse(p_tree,p_visited,tree_len,right);
    149     }
    150 }
    151 
    152 
    153 int tree[TREE_LEN] = {1,2,3,4,5,6,7,8,9,10};
    154 STACK stack ;
    155 
    156 #ifdef REVERSE
    157 int main()
    158 {
    159     int visited[TREE_LEN] = {0};
    160     memset(visited,0,sizeof(visited));
    161 
    162     dfs_reverse(tree,visited,TREE_LEN,0);
    163 }
    164 #else
    165 int main()
    166 {
    167     memset(&stack,0,sizeof(stack));
    168     dfs(&stack,tree,TREE_LEN);
    169 }
    170 #endif

      编译运行结果:

      可以看出结果是符合预期的。代码中对左右子树的处理,是对临接节点处理的一种特殊情况。

  • 相关阅读:
    五、面向对象模型OOM(ObjectOriented Model)
    四、物理数据模型PDM(Physical Data Model )
    Asp.net WebForm中应用Jquery EasyUI Layout
    七、模型文档
    六、PowerDesigner 正向工程 和 逆向工程 说明
    JQuery 原理
    三、概念数据模型CDM(Conceptual Database Model )
    C#基础Func,Action
    Ioc容器应用浅析
    Discuz上面找到的不错的分页算法
  • 原文地址:https://www.cnblogs.com/elseliving/p/8024182.html
Copyright © 2011-2022 走看看