深度优先搜索(DFS)递归与非递归实现逻辑详解

 递归与非递归:

       数据结构对于学习编程的人来说是非常重要的,我们在现实生活碰到的各种烦难问题可以用递归来实现,一个递归思想就把问题给简单化了,但是我们都知道递归是非常耗时的,一旦数据量庞大起来,递归次数多了,这个时间是非常恐怖的。所以一般我们都会把一些递归问题给非递归化,来达到某一定的效率。通常递归转化为非递归用到了栈和队列,今天就详解用栈来实现转化的逻辑处理,并且以(01背包为主讲例子).

      DFS:深度优先搜索,相当于树的先序搜索。在这我们现以数据结构中经典的先序遍历的递归与非递归来打开主题.

                                

     其先序搜索为:1,2,4,5,3;

      递归实现:

void PreorderRecursive(Bitree root){
  if (root) {
    visit(root);
    PreorderRecursive(root->lchild); 
    PreorderRecursive(root->rchild); 
  }
}
    相信递归这个每个人都弄得懂,这里就不BB了.       

    非递归借助栈来完成转化(考研的小伙伴们要弄懂):

void PreorderNonRecursive(Bitree root){
  stack stk;
  stk.push(root);//节点入栈
  while(!stk.empty()){
    p = stk.top();//栈顶元素出栈并且访问该节点
    visit(p);
    stk.pop();
    if(p.rchild) stk.push(stk.rchild);//右边节点入栈
    if(p.lchild) stk.push(stk.lchild);
  }
}
     


           第一步:1号节点入栈。

          第二步:当栈不为空的时候弹出栈顶元素并且访问该节点,当栈为空的时候转第五步。

          第三步:弹出的栈顶元素的右和左节点入栈(如果存在的话).

   

         第四步:转到步骤二。

        第五步:结束。

    相信这个很容易理解。那么我们今天就直扑主题了。

    01背包问题。

    已知 有n个物品  他们的重量分别为 weight[i] = {i1,i2,....,in},价值分别为value[i] = {i1,i2,..in};

    背包的承重为m.求其最大能装下的价值 和.

    首先我们来考虑递归算法。递归逻辑非常简单.

   我们以这个简单例子分析:

    weight[] = {2,2,6};

   value [] = {6,3,5};

  n = 3;

  m = 6;//最大承重量

    static void  Backtrack(int i,int cp,int cw)
    { //cw当前包内物品重量,cp当前包内物品价值
        int j;
        if(i>n)//回溯结束
        {
            System.out.println("over");
            if(cp>bestp)
            {
                System.out.println("if  "+cw);
                bestp=cp;
                for(i=0;i<=n;i++) bestx[i]=x[i];
            }
        }
        else {
             for(j=0;j<=1;j++)  
            {                
                x[i]=j;
                if(cw+x[i]*w[i]<=c)  
                {
                    cw+=w[i]*x[i];
                    cp+=p[i]*x[i];
                    Backtrack(i+1,cp,cw);//递归调用
                    cw-=w[i]*x[i];//开始回溯
                    cp-=p[i]*x[i];
                    System.out.println("x["+i+"]   "+x[i]);
                }//end if
            }//end for
        }//end else
    }//end
         构造我们的回溯树:

      

      黄色线条表示回溯, 先考虑一个背包情况,记录最大值,回溯根节点,判断2个背包,以此回溯。并记录下回溯记录情况,以及选中背包情况.

   懂得了上面的回溯树的构造之后,我们就可以将其改写成非递归。以下是伪代码

    

void Bag(Bitree root){
  stack stk;
  stk.push(root);//节点入栈
  while(!stk.empty()){
    p = stk.top();//栈顶元素出栈并且访问该节点
    visit(p);
    stk.pop();
    if(p.child)  stk.push(stk.child)//从右边开始入栈
  }
}     
      其实好多递归程序不能改写成非递归,重要的是你的树是怎样去构造他。

      最后支持原创,转载请注明转载出处
--------------------- 
作者:年少却很低调 
来源:CSDN 
原文:https://blog.csdn.net/qq_33883389/article/details/78996307 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/u010325193/article/details/85336534
今日推荐