如何从深层递归中跳出?

来源:互联网 发布:centos服务器安全设置 编辑:程序博客网 时间:2024/05/28 19:23

例如我用递归求一个解,当求到解时我想直接跳到主函数结束程序,怎么做?  可以用什么方法及详细使用方法?谢谢

  int   haveSolution   =   0;   
    
  
void   proc()   
  
{   
          
if   (得到可行解)   
                    haveSolution   
=   1;   
                    
//跳到main函数注释行   
          else   
                  
//递归调用   
                  proc();   
          
return;   
  }
   
    
  
void   main()   
  
{   
          proc();   
          
if   (haveSolution)         /*跳到这里   */   
                    cout   
<<   "got   the   solution";   
          
else   
                    cout   
<<   "not";   
          
return;   
  }

iamcaicainiao(老菜,长征)

int   haveSolution   =   0;   
  #include   
<iostream.h>   
    
  
int   proc()   
  
{   
          
if   (1){//得到可行解   
                    haveSolution   =   1;   
                    
return   1;   
                    
//跳到main函数注释行   
  }
   
          
else   
  
{   
                  
//递归调用   
                  proc();   
  
return   0;   
  }
   
          
return   2;   
  }
   
    
  
void   main()   
  
{   
  
int   i   =   proc();   
          
if   (i==1){   
                    
if   (haveSolution)         /*跳到这里   */   
                            cout   
<<   "got   the   solution";   
                    
else   
                          cout   
<<   "not";   
          }
else   if(i==2){   
  ……   
  }
else   if(i==0){   
                      ……   
  }
else   
  
{   
                      ……   
                    }
   
    
return;   
  }
   

caijize(砂子)
楼主的思路不是很好,要直接跳出就不要用递归,     要用递归就得一个个地跳回去,否则就会造成内存泄漏。   
建议楼主再仔细地看看递归的使用方法和使用条件。    
按照楼主的意思,应该这样实现:  

 

int   haveSolution   =   0;   
    
  
void   proc()   
  
{   
          
////////////////////   
          //求解   
                ……   
          
/////////////     
    
          
if   (得到可行解)   
                    haveSolution   
=   1;   
          
else   
                  
//递归调用   
                  proc();   
          
return;   
  }
   
    
  
void   main()   
  
{   
          proc();   
          
if   (haveSolution)         
                    cout   
<<   "got   the   solution";   
          
else   
                    cout   
<<   "not";   
          
return;   
  }
   

pagechen(天外飞来的仙)
我想longjmp   和   setjmp   两个函数可以帮助你。  
不过如果不理解内涵,比较难用


alvachien(白衣战神,四大绝技:C#/C++/T-SQL/ABAP)
简单,直接跳使用throw一个exception就出来了。  
完全可以通过throw一个特定的类型来达到直接跳出的效果。


vc_hunter(飞天御箭)
可以用内嵌汇编的方式修改ebp或esp,这方法虽然可用,但会使程序变得很难看懂。而且,不对WIN32汇编有一定了解,实现起来不是很容易

 

/*实现了深度递归加跳出,或许该叫递推?*/   
  #include   
"stdafx.h"   
  #include   
"windows.h"   
  
int   digui(int   n,int   value,int   retadd)   
  
{   
  
if(retadd==0)   
  
{   
  __asm   
  
{   
  mov   retadd,ebp 
//保存第一次进入时的返回地址   
  }
   
    
  }
   
  
if(n==1)   
  
{   
  __asm 
//求得结果后直接返回main   
  {   
  mov   eax,value   
  mov   ebp,retadd   
  mov   esp,ebp   
  pop   ebp   
  ret   
  }
   
  }
   
  
else   
  
{   
  digui(n
-1,value*2,retadd);   
  }
   
    
  ::Sleep(
9999999999);   
  
return   0;   
  }
   
  
void   main(int   argc,   char*   argv[])   
  
{   
  
int   a=digui(5,2,0);//求2的5次方   
  printf("%d",a);   
    
    
    
  }

pankun(剑神一笑 Console下面干革命)
递归要一步步ret,不然堆栈不会平衡.用楼上改esp的方法当然也可以.

pagechen(天外飞来的仙)
longjmp   和   setjmp   就是C实现远程跳转的好方法,是对修改ebp方法的封装。  
throw   好吗?假设你在第100层递规中药退出,你要throw多少层啊?浪费啊

ox_thedarkness()
厄,很有趣的问题。分别有   C、   C++   两种方法可以解决你的问题。  
C方法是:使用标准库<csetjmp>或者<setjmp.h>中的   setjmp   和   longjmp。注意,前面所谓   goto   的方法是错误的。   goto   不能完成函数间跳转。  
C++方法简洁得多:   抛出异常;函数调用时则用   try   ...   catch   捕获异常。  
下面给出C++方法的一个例子。

 

  //   判断   n   是否奇数   
  
//   结果由   throw   抛出,奇数抛出true,否则抛出false   
  void   isOdd(   unsigned   int   n   ){   
      
if(   n   ==   0   )   throw   false;   
      
if(   n   ==   1   )   throw   true;   
      isOdd(   n   
-   2   );   
  }
   
    
  
//不过调用起来就有些麻烦:   
    
  
int   main(){   
      
//   用法类似这样   
      try{   
          isOdd(   
21   );   
      }
catch(   bool   odd   ){   
          cout
<<   (   odd?   "odd"   :   "even"   )<<   endl;   
      }
   
  }

一个问题是,上面三种方法都不是透明的。isOdd   不能像一般函数一样使用,而必须详细阅读和理解设计者的文档,正确使用晦涩的   __asm、   setjump   、try   catch等等、否则会令程序崩溃。这不是好的设计。  
一个解决方案是:给递归部分一个壳。使用两个函数,递归函数负责递归,壳函数负责这些复杂的调用过程,用户只调用壳函数。  
为了避免用户调用递归函数,以及命名冲突问题,可以使用   nest   function   技术。   C/C++本身不直接支持内嵌函数,但是我们可定义一个局部struct,把内嵌的函数定义为其static成员

 

//   若   n   是奇数,返回true,   否则返回   false   
  
//   内嵌函数递归   +   通过异常机制实现   
  bool   isOdd(   unsigned   int   n   ){   
      
//   一个Nest   struct,   用于定义一个   nest   函数   
      struct   Nst   {   
          
//   递归计算n是否奇数,计算完成时throw   bool   
          static   void   recurve(   unsigned   int   n   ){   
              
if(   n   ==   0   )   throw   false;   
              
if(   n   ==   1   )   throw   true;   
              recurve(   n   
-   2   );   
          }
   
      }
;   
    
      
try{   
          Nst::recurve(   n   );   
      }
catch(   bool   odd   ){   
          
return   odd;   
      }
   
  }
   

Nst   是   isOdd   函数内部定义的结构,他的名字只在   isOdd   内可见。所以你可以在所有函数内一致使用   Nst   作为内嵌结构的名字,而不会出现任何冲突。  
  现在   isOdd   是一个正常函数,可以正常调用了:    

  int   main()
 
{   
      cout
<<   (   isOdd(   32   )?"odd":"even"   )   <<endl;   
  }
  

   下面是C风格的实现:  
  -----------------------------------------------------  
  我们使用<setjmp.h>中   setjmp   和   longjmp的方法实现跳转。    
  注意,纯C中结构不能有成员函数,所以nest   function   技巧行不通了。另外C不支持bool,所以我们返回int。当然   C++   编译器可以继续支持混合程序的技巧。    
  为了符合C标准,我们将定义一个额外的函数,两个额外的静态全局变量。这些额外的标识符都使用长名称,并且加上static限定词   ——   以便避免对全局名字空间更大的污染。     
  另外,   C99之前的C标准中,外部连接的标识符只有前六个字母有效   ——   所以若是不加static限定词,我们就给上面的三个标识符取长长的名字就有危险啦,譬如那个recurve_is_odd。(C99之前的标准中,内部连接的标识符前31个字母为有效字符)   
   

//   is_odd函数的实现细节。   
  
//   !不要直接调用recurve_is_odd函数、或者访问下面两个变量   
  static   jmp_buf   jb_is_odd;   
  
static   int   n_is_odd;   
  
static   void   recurve_is_odd(   unsigned   int   n   ){   
      
if(   n   ==   0   )   {   n_is_odd   =   0;   longjmp(   jb_is_odd,   1   );   }   
      
if(   n   ==   1   )   {   n_is_odd   =   1;   longjmp(   jb_is_odd,   1   );   }   
      recurve_is_odd(   n   
-   2   );   
  }
   
    
  
//   若   n   是奇数,返回true,   否则返回   false   
  
//   函数递归,   通过setjmp   longjmp实现   
  int   is_odd(   unsigned   int   n   ){   
      
if(   setjmp(   jb_is_odd   )   ==   0   )   
          recurve_is_odd(   n   );   
      
else   
          
return   n_is_odd;   
  }
   
    
  
int   main(){   
      
if(   is_odd(   23   ))   printf(   "odd "   );   
      
else   printf(   "even "   );   
  }
   

 

 

 

原创粉丝点击