(转)如果要用Java实现算法,一定慎用递归

通过一个求和算法的实例,对比了递归与非递归两种实现方式的性能差异,结果显示非递归实现比递归实现快约1/3。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

现象 :

递归是我们很经典的一种算法实现,可以很好的描述一个算法的原理!对于算法的描述、表现和代码结构理解上,递归都是不错的选择!

但是本文想说的是java实现一个递归算法的时候尽量不要用递归实现,而是转换成的非递归实现  。

最近在实现一个比较复杂算法的时候,尝试了一下,非递归实现相比递归实现速度上能提升1/3  。

以下面一个简单的例子来说:(注:为了描述简单,所以这里只用一个简单的例子)

输入参数:N

输出结果: log1+log2+log3+....+logN

两种实现代码如下:

Java代码

 

 

  1. package test;     
  2.     
  3. public class RecursiveTest {     
  4.     /**    
  5.      * 递归实现    
  6.      *     
  7.      * @param n    
  8.      * @return    
  9.      */    
  10.     public static double recursive(long n) {     
  11.         if (n == 1) {     
  12.             return Math.log(1);     
  13.         } else {     
  14.             return Math.log(n) + recursive(n - 1);     
  15.         }     
  16.     }     
  17.     
  18.     /**    
  19.      * 非递归实现    
  20.      *     
  21.      * @param n    
  22.      * @return    
  23.      */    
  24.     public static double directly(long n) {     
  25.         double result = 0;     
  26.         for (int i = 1; i <= n; i++) {     
  27.             result += Math.log(i);     
  28.         }     
  29.         return result;     
  30.     }     
  31.     
  32.     public static void main(String[] args) {     
  33.         int i = 5000000;     
  34.         long test = System.nanoTime();     
  35.         long start1 = System.nanoTime();     
  36.         double r1 = recursive(i);     
  37.         long end1 = System.nanoTime();     
  38.         long start2 = System.nanoTime();     
  39.         double r2 = directly(i);     
  40.         long end2 = System.nanoTime();     
  41.     
  42.         System.out.println("recursive result:" + r1);     
  43.         System.out.println("recursive time used:" + (end1 - start1));     
  44.         System.out.println("non-recursive result:" + r2);     
  45.         System.out.println("non-recursive time used:" + (end2 - start2));     
  46.     }     
  47. }    

 

得到运行结果如下:

 

  1. recursive result:7.212475098340103E7  
  2. recursive time used:539457109   
  3. non-recursive result:7.212475098340103E7  
  4. non-recursive time used:282479757  

 

可以看出递归的运行时间是非递归运行时间将近2倍  。

(注:以上代码还是在-Xss200m的参数下运行的,如果栈空间不足,直接不能运行)

原因简单分析:

 

 

上图是java线程栈的结构  。java将为每个线程维护一个堆栈,堆栈里将为每个方法保存一个栈帧,栈帧代表了一个方法的运行状态  。 也就是我们常说的方法栈  。最后一个为当前运行的栈帧  。

那么每一次方法调用会涉及:

1.为新调用方法的生成一个栈帧

2.保存当前方法的栈帧状态

3.栈帧上下文切换,切换到最新的方法栈帧  。

递归实现将导致在栈内存的消耗(往往需要调整Xss参数)和因为创建栈帧和切换的性能开销,最终大大的影响效率!

所以,如果你想提升你的算法效率,不要使用递归实现是一个基础原则!

另外,递归是我们用来理解算法的一个方法,当用代码来实现的时候基本都可以转换成非递归的代码实现!

<think>嗯,用户想知道如何在编程中提前终止递归调用。这个问题涉及到递归的基本原理和控制流程。首先,我需要回忆递归是如何工作的。递归函数会不断调用自身,直到满足某个终止条件。如果用户想提前终止,可能是在某些情况下不需要继续递归了,比如找到了需要的解或者检测到错误。 那不同的编程语言可能有不同的方法。比如,像Python这样的语言,通常是通过条件判断来提前返回,从而停止递归。例如,在递归函数中,当某个条件满足时,立即返回结果,不再进行后续的调用。不过,用户可能需要更明确的终止方式,比如抛出异常,但这可能不是最佳实践,因为异常处理通常用于错误情况,而不是正常的控制流程。 接下来,我需要考虑其他语言,比如Java或C++,是否有不同的机制。例如,使用标志变量或者检查全局变量来跳出递归。但这种方法可能不够优雅,或者存在线程安全问题。此外,有些语言可能支持尾递归优化,但提前终止可能仍然需要条件判断。 然后,用户可能的问题场景是什么?比如,在搜索算法中,找到目标后立即停止递归,避免不必要的计算。这时候,如何有效地传递终止信号是关键。可能的方法包括返回特定的值,或者通过引用参数传递状态标志。 还需要注意递归的堆栈问题。如果递归深度很大,提前终止可以避免堆栈溢出。这时候,条件检查的位置很重要,应该在每次递归调用前检查是否满足终止条件。 可能用户对如何设计递归函数的终止条件不太清楚,或者遇到了无法正常退出的情况。需要强调在递归函数中必须有明确的终止条件,并且确保在满足条件时立即返回,避免继续调用。 另外,错误处理机制如异常是否适用于提前终止?例如,在Python中抛出异常并在外层捕获,这样可以立即跳出所有递归层。但这种方法可能影响代码的可读性和性能,需要权衡利弊。 总结起来,主要的解决方案是在递归函数中添加条件判断,一旦满足终止条件,立即返回。此外,可能需要设计返回值来传递终止信号,或者使用异常机制,但需谨慎使用。不同语言的具体实现可能有所不同,但核心思想是控制递归的流程,及时停止不必要的调用。</think>在编程中提前终止递归调用通常需要结合条件判断和返回值设计。以下是几种常见方法及具体实现示例: ### 一、基础条件判断法 在递归函数中设置明确的终止条件,当条件满足时立即返回: ```python def factorial(n): if n < 0: # 异常条件提前终止 return -1 # 约定错误代码 if n == 0: # 正常终止条件 return 1 return n * factorial(n-1) ``` 当输入负数时立即返回错误代码[^3]。 ### 二、标志位传递法 通过参数传递终止标志(适用于支持引用传递的语言): ```python def search(arr, index, target, found=False): if found: # 提前终止 return True if index >= len(arr): return False if arr[index] == target: return True return search(arr, index+1, target, found) ``` ### 三、异常中断法(慎用) 通过抛出异常强制终止递归调用栈: ```python class StopRecursion(Exception): pass def recursive_func(): if 终止条件: raise StopRecursion recursive_func() try: recursive_func() except StopRecursion: print("递归已终止") ``` 这种方法会破坏代码执行流程,需谨慎使用[^2]。 ### 四、尾递归优化模式 虽然多数语言不直接支持尾递归优化,但可模拟实现: ```python def tail_recursive(n, acc=1): if n == 0: return acc return tail_recursive(n-1, acc*n) # 最后一步直接返回递归结果 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值