当前位置:  编程技术>java/j2ee

java 递归深入理解

    来源: 互联网  发布时间:2014-10-22

    本文导语:  递归:一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。本案例很清楚的说明了递归是如何将一个复杂的问题转化为规...

递归:一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。本案例很清楚的说明了递归是如何将一个复杂的问题转化为规模较小的问题来解决的。下面通过一个小例子来说明递归的原理。
代码如下:

/**
* @fileName Test.java
* @description 递归学习比较,求阶乘
* @date 2012-11-25
* @time 17:30
* @author wst
*/
public class Test {
static int multiply(int n) {
int factorial;// 阶乘
if (n == 1 || n == 0) {
factorial = n;
} else {
factorial = n * multiply(n - 1);
}
return factorial;
}
public static void main(String[] args) {
System.out.println(multiply(5));
}
}

当函数被调用时,它的变量的空间是创建于运行时堆栈上的。以前调用的函数的变量扔保留在堆栈上,但他们被新函数的变量所掩盖,因此 是不能被访问的。
程序中的函数有两个变量:参数n和局部变量factorial。下面的一些图显示了堆栈的状态,当前可以访问的变量位于栈顶。所有其他调用的变量饰以灰色的阴影,表示他们不能被当前正在执行的函数访问。
假定我们以5这个值调用递归函数。堆栈的内容如下,栈顶位于最下方:
代码如下:

n multiply(n) factorial
5 multiply(5) 5*multiply(4) //第一次调用
4 multiply(4) 4*multiply(3) //第二次调用
3 multiply(3) 3*multiply(2) //第三次调用
2 multiply(2) 2*multiply(1) //第四次调用
1 multiply(1) 1 //第五次调用

从上面的信息可以很容易的看出,递归是如何将一个问题逐渐最小化来解决的,从方法调用开始,factorial结果都会被压入栈,直到方法调用结束,最后从栈顶逐个返回得到结果。经过逐个代入,结果如下:
n=1 1 向上返回 1
n=2 2*multiply(1) 向上返回 2*1=2
n=3 3*multiply(2) 向上返回 3*(2*1)=6
n=4 4*multiply(3) 向上返回 4*(3*(2*1))=24
n=5 5*multiply(4) 向上返回 5*(4*(3*(2*1)))=120
注意:因为multiply(1)或multiply(0)返回的值为1
所以就有 2*multiply(1)=2*1=2
又因为multiply(2)符合递归条件,递归后可化为2*multiply(1)
所以就有3*multiply(2)=3*(2*multiply(1))=3*(2*1)=6
因为multiply(3)递归后可化为3*multiply(2)
所以multiply(4)=4*multiply(3)=4*(3*multiply(2))=4*(3*(2*1))=24
以此类推,multiply(5)=5*multiply(4)
可化为5*(4*multiply(3))=5*(4*3*(multiply(2)))=5*(4*(3*(2*1)))=120
再来看看字节码信息:
代码如下:

public class Test extends java.lang.Object{
public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return
static int multiply(int);
Code:
0: iload_0
1: iconst_1 //将int类型常量1压入栈
2: if_icmpeq 9 //将两个int类型值进行比较,相等,则跳转到位置9,这就是||的短路功能
5: iload_0 //此处是在第一个条件不成立的情况下执行,从局部变量0中装载int类型值(将n的值压入栈)
6: ifne 14 //比较,如果不等于0则跳转到位置14,注意:由于此处默认和0比较,所以没有必要再将常量0压入栈
9: iload_0 //如果在ifne处没有跳转,则从局部变量0中装载int类型值(将n的值压入栈)
10: istore_1 //将int类型值存入局部变量1中(弹出栈顶的值即局部变量0压入栈的值,再存入局部变量1中)
11: goto 23 //无条件跳转至位置23
14: iload_0 //位置6处的比较,如果不等于0执行此指令,从局部变量0中装载int类型值(将n的值压入栈)
15: iload_0 //从局部变量0中装载int类型值(将n的值压入栈)
16: iconst_1 //将int类型常量1压入栈,常量1是代码中n-1的1
17: isub //执行减法操作,n-1
18: invokestatic #2; //Method multiply:(I)I,调用方法multiply
21: imul //执行乘法操作,n * multiply(n - 1)
22: istore_1 //将int类型值存入局部变量1中,factorial=...
23: iload_1 //从局部变量1中装载int类型值(将factorial的结果压入栈)
24: ireturn //方法返回
public static void main(java.lang.String[]);
Code:
0: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
3: iconst_5
4: invokestatic #2; //Method multiply:(I)I
7: invokevirtual #4; //Method java/io/PrintStream.println:(I)V
10: return
}

    
 
 

您可能感兴趣的文章:

  • 请问java里可有递归吗?
  • 在java里,递归的程序怎么写??麻烦随便写个例子出来。谢谢!
  • Java递归 遍历目录的小例子
  • java 用递归获取一个目录下的所有文件路径的小例子
  • java能否实现递归调用,入门级问题!!欢迎大家讨论!
  • java 汉诺塔Hanoi递归、非递归(仿系统递归)和非递归规律 实现代码
  • 快速排序算法原理及java递归实现
  • Java递归算法的使用分析
  • 关于数据库查询的java递归程序怎么写?最好有例子
  • java递归菜单树转换成pojo对象
  • 如何用java实现递归?给n个整数,写出计算结果为24的算法,要所有数都用上,只用加减乘除实现
  • 想深入学习Java应该学习哪些东西
  • 深入理解Java对象实例生成的例子
  • java父类和子类初始化顺序的深入理解
  • 深入分析Java内存区域的使用详解
  • 基于Java Tomcat和激活MyEclips的深入理解
  • java/word+fusionchart生成图表深入分析
  • 深入理解:Java是类型安全的语言,而C++是非类型安全的语言
  • Java接口和抽象类的区别深入剖析
  • 深入JAVA对象深度克隆的详解
  • 深入Java不可变类型的详解
  • 深入java对象复制的分析
  • 深入探讨java的接口和抽象的内涵!
  • 基于Java实现缓存Cache的深入分析
  • java加密枝术深入理解
  • 深入探讨java的接口和抽象的内涵!(续上贴,上贴分已给)
  • 基于Java protected的深入理解
  • 深入Ajax代理的Java Servlet的实现详解
  • 虚函数与纯虚函数(C++与Java虚函数的区别)的深入分析
  • 一个头疼的问题,请对java多态性有深入了解的高手给予关注
  • 深入解析java中的locale
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 求最容易理解,最容易上手的java书籍,servlet书籍,请指教,谢谢!!
  • 各位老兄对java的多态性是如何理解的?java的多态性有什么好处?
  • 如何理解JAVA中的stream?
  • 我对java虚拟机的理解,大家共同探讨
  • 关于java的访问控制和继承,这段话怎么理解?
  • 一个比较难理解的问题(关于Java类的概念)
  • 初学java,对throw 抛出个新异常不很理解。请哪为高人可以帮忙解释下么?谢谢
  • java String 类的一些理解 关于==、equals、null
  • Java事务的个人理解小结
  • 关于Java中的toString()函数有一点理解不透。
  • 基于Java字符串 "==" 与 "equals" 的深入理解
  • java及C++中传值传递、引用传递和指针方式的理解
  • 深入理解Java中的字符串类型
  • 在机械工业出版社出的《JAVA 编程思想》中,一句关于内部类的话不理解?
  • 深入理解Java编程中异常处理的优劣
  • 真正理解JAVA的高手请进来挑战挑战!
  • 深入理解Java对象的序列化与反序列化的应用
  • 深入理解java中的synchronized关键字
  • Java线程中断的本质深入理解
  • Java中HashMap和TreeMap的区别深入理解
  • java命名空间java.sql类types的类成员方法: java_object定义及介绍
  • 我想学JAVA ,是买THINK IN JAVA 还是JAVA2核心技术:卷1 好???
  • java命名空间java.awt.datatransfer类dataflavor的类成员方法: imageflavor定义及介绍
  • 请问Java高手,Java的优势在那里??,Java主要适合于开发哪类应用程序
  • java命名空间java.lang.management类managementfactory的类成员方法: getcompilationmxbean定义及介绍
  • 如何将java.util.Date转化为java.sql.Date?数据库中Date类型对应于java的哪个Date呢
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getlibrarypath定义及介绍
  • 谁有电子版的《Java编程思想第二版(Thinking in java second)》和《Java2编程详解(special edition java2)》?得到给分
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getstarttime定义及介绍
  • 本人想学java,请问java程序员的待遇如何,和java主要有几个比较强的方向
  • java命名空间java.awt.datatransfer类dataflavor的类成员方法: stringflavor定义及介绍


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3