如何从深层递归中跳出?
来源:互联网 发布:centos服务器安全设置 编辑:程序博客网 时间:2024/05/28 19:23
例如我用递归求一个解,当求到解时我想直接跳到主函数结束程序,怎么做? 可以用什么方法及详细使用方法?谢谢
void proc()
...{
if (得到可行解)
haveSolution = 1;
//跳到main函数注释行
else
//递归调用
proc();
return;
}
void main()
...{
proc();
if (haveSolution) /**//*跳到这里 */
cout << "got the solution";
else
cout << "not";
return;
}
iamcaicainiao(老菜,长征)
#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(砂子)
楼主的思路不是很好,要直接跳出就不要用递归, 要用递归就得一个个地跳回去,否则就会造成内存泄漏。
建议楼主再仔细地看看递归的使用方法和使用条件。
按照楼主的意思,应该这样实现:
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++方法的一个例子。
// 结果由 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成员
// 内嵌函数递归 + 通过异常机制实现
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 是一个正常函数,可以正常调用了:
...{
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个字母为有效字符)
// !不要直接调用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 " );
}
- 如何从深层递归中跳出?
- 如何从深层嵌套的循环中迅速跳出
- WPF中,如何从Toolbar中跳出Tab循环
- WPF中,如何从Toolbar中跳出Tab循环
- 如何从一个多重循环中直接跳出
- 如何从Runnable内部跳出ScheduledExecutorService.scheduleAtFixedRate
- js如何从循环跳出方法
- 如何在LandaV8中使用跳出地段
- Jquery each方法中如何 跳出、继续
- java中如何跳出多重循环
- gtest中如何跳出当前测试案例
- java中如何跳出多重嵌套循环?
- Java中如何跳出多层循环
- java中如何跳出多层循环
- Java中如何一次跳出多层循环
- Java中如何跳出指定循环
- java中如何跳出多重循环
- 在Java中,如何跳出多重循环
- SQL循序渐进(23)UNION 和 外部连接
- 编写和建立存储过程,并定义合适的过程返回状态码和信息
- 情尽桥
- 又一次生日
- SQL循序渐进(24)嵌入SQL
- 如何从深层递归中跳出?
- SQL循序渐进(22)EXISTS 和 ALL
- Spring的事务,经典配置
- VML Chart 控件
- 用Javascript制作一个可自动填写的文本框(二)
- SQL循序渐进(20)Aliases 、In以及子查询
- 用Javascript制作一个可自动填写的文本框(全文完)
- JavaScript对象与数组参考大全
- 怎样用Javascript获得IE临时目录