如果要用Java实现算法,一定慎用递归
来源:互联网 发布:管家婆软件下载中心 编辑:程序博客网 时间:2024/05/22 04:40
现象 :
递归是我们很经典的一种算法实现,可以很好的描述一个算法的原理!对于算法的描述、表现和代码结构理解上,递归都是不错的选择!
但是本文想说的是java实现一个递归算法的时候尽量不要用递归实现,而是转换成的非递归实现。
最近在实现一个比较复杂算法的时候,尝试了一下,非递归实现相比递归实现速度上能提升1/3。
以下面一个简单的例子来说:(注:为了描述简单,所以这里只用一个简单的例子)
输入参数:N
输出结果: log1+log2+log3+....+logN
两种实现代码如下:
Java代码
- package test;
- public class RecursiveTest {
- /**
- * 递归实现
- *
- * @param n
- * @return
- */
- public static double recursive(long n) {
- if (n == 1) {
- return Math.log(1);
- } else {
- return Math.log(n) + recursive(n - 1);
- }
- }
- /**
- * 非递归实现
- *
- * @param n
- * @return
- */
- public static double directly(long n) {
- double result = 0;
- for (int i = 1; i <= n; i++) {
- result += Math.log(i);
- }
- return result;
- }
- public static void main(String[] args) {
- int i = 5000000;
- long test = System.nanoTime();
- long start1 = System.nanoTime();
- double r1 = recursive(i);
- long end1 = System.nanoTime();
- long start2 = System.nanoTime();
- double r2 = directly(i);
- long end2 = System.nanoTime();
- System.out.println("recursive result:" + r1);
- System.out.println("recursive time used:" + (end1 - start1));
- System.out.println("non-recursive result:" + r2);
- System.out.println("non-recursive time used:" + (end2 - start2));
- }
- }
得到运行结果如下:
- recursive result:7.212475098340103E7
- recursive time used:539457109
- non-recursive result:7.212475098340103E7
- non-recursive time used:282479757
可以看出递归的运行时间是非递归运行时间将近2倍。
(注:以上代码还是在-Xss200m的参数下运行的,如果栈空间不足,直接不能运行)
原因简单分析:
上图是java线程栈的结构。java将为每个线程维护一个堆栈,堆栈里将为每个方法保存一个栈帧,栈帧代表了一个方法的运行状态。 也就是我们常说的方法栈。最后一个为当前运行的栈帧。
那么每一次方法调用会涉及:
1.为新调用方法的生成一个栈帧
2.保存当前方法的栈帧状态
3.栈帧上下文切换,切换到最新的方法栈帧。
递归实现将导致在栈内存的消耗(往往需要调整Xss参数)和因为创建栈帧和切换的性能开销,最终大大的影响效率!
所以,如果你想提升你的算法效率,不要使用递归实现是一个基础原则!
另外,递归是我们用来理解算法的一个方法,当用代码来实现的时候基本都可以转换成非递归的代码实现!
- 如果要用Java实现算法,一定慎用递归
- java中为什么我们要慎用递归
- 慎用Java递归调用
- 【笔记】慎用Java递归调用
- java递归算法实现
- java递归算法实现
- 递归算法 Java实现
- java递归算法实现
- 用java实现的经典递归算法
- 用java实现的经典递归算法
- 用java实现的经典递归算法
- Java归并算法递归实现
- 用java实现:利用递归算法返转一个整数
- (Java)用递归算法实现斐波那契数列
- java用递归实现的数组排列算法
- Java动态编译要慎用
- 【Fiay】【Java】汉诺塔算法 递归实现
- 【递归经典题目】汉诺塔算法 Java实现
- [android] EditText的setError文字不显示问题
- SQL函数学习(函数在实际项目中 之 COALESCE)
- 封装一个工具类:回收任何布局中被Imageview吃掉的内存(附源码DEMO)
- ssh 登录提示出错
- 中国余数定理
- 如果要用Java实现算法,一定慎用递归
- 英尺对米的转换
- vmware加载u盘
- POJ 1917 Automatic Poetry
- HDU 1717 循环小数化分数
- 角点检测(Corner Detection) cvFindCornerSubPix 使用范例
- android
- 2012-2013年世界大学计算机专业排名
- Android开发--图形图像与动画(二)--Animation实现图像的 渐变、缩放、位移、旋转