java 递归深入理解

一、递归函数,通俗的说就是函数本身自己调用自己...

如:n!=n(n-1)!
你定义函数f(n)=nf(n-1)

而f(n-1)又是这个定义的函数。。这就是递归

二、为什么要用递归:递归的目的是简化程序设计,使程序易读

三、递归的弊端:虽然非递归函数效率高,但较难编程,可读性较差。递归函数的缺点是增加了系统开销,也就是说,每递归一次,栈内存就多占用一截

四、递归的条件:需有完成任务的语句,需满足递归的要求(减小而不是发散)

五、递归进阶:
1.用递归算n的阶乘:

分析:n!=n*(n-1)*(n-2)...*1

 public int dReturn(int n){
   if(n==1){
    return 1;
   }else{
    return n*dReturn(n-1);
   }
  } 

2.用递归函数算出1到n的累加:1+2+3+4+..+n

 public int dReturn(int n){
  if(n==1){
   return 1;
  }else{
   return n+dReturn(n-1);
  }
 } 

3.要求输出一个序列:1,1,2,3,5,8,11......(每一个数为前两个数子之和,要求用递归函数)
  用java递归来表示一个函数:F(n)=F(n-1)+F(n-2);F(0)=1;F(1)=1;
   分析:X1=1; X2=1; X3=X1+X2; X4=X2+X3; ... ; Xn=X(n-1)+X(n-2)

  public int F(int n){
  if(n==1){
   return 1;
  }else if(n==2){
   return 1;
  }else{
    return F(n-1)+F(n-2);
  }
 } 

4.java用递归方法反向打印一个整数数组中的各个元素

  public static void printAll(int index,int[] arr){
   System.out.println(arr[index]);
   if(index > 0){
    printAll(--index,arr);
   }
  }
  public static void main(String[] args){
   int[] arr={1,2,3,4,5};
   printAll(arr.lenth-1,arr);
  } 

5.编程求解:若一头小母牛,从出生起第四个年头开始每年生一头母牛,按次规律,第 n 年时有多少头母牛?

  public static int cattle(int n){
if(n<=0){
 return 0;
}else if(n<=3){
 return 1;
}else{
 return cattle(n-1)+cattle(n-3);
}
  }
  public static void main(String[] args){
   int n=10;
   System.out.println(n+"年后共有"+cattle(n)+"头牛");
  } 

递归、线性递归、尾递归的概念?

Java中递归函数的调用-求一个数的阶乘

不考虑溢出:一般只能算到69的阶乘……

注意:0的阶乘0!=1

任何大于1的自然数n阶乘表示方法:
n!=1×2×3×……×n
或n!=n×(n-1)!
搜索0的阶乘,可以出来一个在线计算器,很实用哦!!

package test;

import java.util.Scanner;

public class DiGui {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("输入一个整数:");
		Scanner scan = new Scanner(System.in);
		int x = scan.nextInt();
		int result = digui(x);
		System.out.println(result);
	}

	//递归函数
	public static int digui(int x){
		if(x<=0){
			return 1;
		}else{
			return x*digui(x-1);
		}
	}
}

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

/**
* @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."<init>":()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
} 
(0)

相关推荐

  • 快速排序算法原理及java递归实现

    快速排序 对冒泡排序的一种改进,若初始记录序列按关键字有序或基本有序,蜕化为冒泡排序.使用的是递归原理,在所有同数量级O(n longn) 的排序方法中,其平均性能最好.就平均时间而言,是目前被认为最好的一种内部排序方法 基本思想是:通过一躺排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列. 三个指针: 第一个指针称为pivotkey指针(枢轴),第二个指

  • java递归菜单树转换成pojo对象

    复制代码 代码如下: package com.cjonline.foundation.authority.pojo;import java.util.ArrayList;import java.util.Collections;import java.util.Iterator;import java.util.List;import org.apache.log4j.Logger;import com.cjonline.foundation.util.CheckNullEmpty;/** *

  • Java递归遍历树形结构

    废话不多说了,直接给大家贴代码,具体代码如下所示: //菜单树形结构 public JSONArray treeMenuList(JSONArray menuList, int parentId) { JSONArray childMenu = new JSONArray(); for (Object object : menuList) { JSONObject jsonMenu = JSONObject.fromObject(object); int menuId = jsonMenu.ge

  • Java递归算法的使用分析

    递归算法是一种直接或者间接地调用自身的算法.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解. 问题1:一列数的规则如下: 1.1.2.3.5.8.13.21.34 ,求第30位数是多少?使用递归实现 复制代码 代码如下: public class FibonacciSequence {    public static void main(String[] args){        System.out.println(Fribonacci(9))

  • java 用递归获取一个目录下的所有文件路径的小例子

    复制代码 代码如下: private List<String> ergodic(File file,List<String> resultFileName){        File[] files = file.listFiles();        if(files==null)return resultFileName;// 判断目录下是不是空的        for (File f : files) {            if(f.isDirectory()){// 判

  • java 汉诺塔Hanoi递归、非递归(仿系统递归)和非递归规律 实现代码

    程序如下: 复制代码 代码如下: View Code  /*  * Hanoi塔游戏 问题描述:  * 汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具.  * 大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照  * 大小顺序摞着64片黄金圆盘.大梵天命令婆罗门把圆盘从下面开始按大小  * 顺序重新摆放在另一根柱子上.并且规定,在小圆盘上不能放大圆盘,在  * 三根柱子之间一次只能移动一个圆盘.  *   * fuction:实现 hanoi塔  *       

  • Java中的递归详解(用递归实现99乘法表来讲解)

    1:普通实现99乘法表太简单,是个程序员都会,实现如下: package test.ms; public class Test99 { public static void main(String[] args) { for(int i=1; i<=9;i++){ for(int j=1; j<=i; j++){ System.out.print(j+" * "+i+ " = "+(i*j) +" "); } System.out.p

  • Java递归算法详解(动力节点整理)

    递归算法是一种直接或者间接调用自身函数或者方法的算法.Java递归算法是基于Java语言实现的递归算法.递归算法的实质是把问题分解成规模缩小的同类问题的子问题,然后递归调用方法来表示问题的解.递归算法对解决一大类问题很有效,它可以使算法简洁和易于理解.    递归算法解决问题的特点: 1)递归就是方法里调用自身.  2) 在使用递增归策略时,必须有一个明确的递归结束条件,称为递归出口.  3)递归算法解题通常显得很简洁,但递归算法解题的运行效率较低.所以一般不提倡用递归算法设计程序.  4)在递

  • Java算法之递归算法计算阶乘

    本文为大家分享的java算法计算阶乘,在学习Java课程时经常会遇到求阶乘问题,今天接跟大家一起探讨一下 代码如下: package com.xu.main; import java.util.Scanner; public class P9 { static long fact(int n) { if(n <= 1) { return 1; } else { return n * fact(n - 1); } } public static void main(String[] args) {

  • java 递归深入理解

    一.递归函数,通俗的说就是函数本身自己调用自己... 如:n!=n(n-1)! 你定义函数f(n)=nf(n-1) 而f(n-1)又是这个定义的函数..这就是递归 二.为什么要用递归:递归的目的是简化程序设计,使程序易读 三.递归的弊端:虽然非递归函数效率高,但较难编程,可读性较差.递归函数的缺点是增加了系统开销,也就是说,每递归一次,栈内存就多占用一截 四.递归的条件:需有完成任务的语句,需满足递归的要求(减小而不是发散) 五.递归进阶: 1.用递归算n的阶乘: 分析:n!=n*(n-1)*(

  • java迷宫算法的理解(递归分割,递归回溯,深搜,广搜)

    最近这学期做了一个java迷宫的课程设计,这里代码及其算法逻辑就分享出来. 首先简单的说一下其中我使用的算法(自动生成地图:递归分割法.递归回溯法:寻找路径:深度优先.广度优先算法) 递归分割法: 地图外面一圈被墙围住,然后在空白区域生成十字墙壁,再随机选择三面墙,将其打通,这样就能保证迷宫的流动性,再分别对刚才分好的四个区域以同样的方式执行分割,一直递归下去,直到空间不足以分割就return. 递归回溯法: 递归回溯法与深度优先算法在大致算法上其实差不多,具体只有一些细微的差别,都是通过判断当

  • Java递归运行的机制:递归的微观解读图文分析

    本文讲述了Java递归运行的机制:递归的微观解.分享给大家供大家参考,具体如下: 前言:在java递归基础与递归的宏观语意和java链表的天然递归结构性质中我们分别通过数组以及链表对递归进行了应用,那时我们只是对递归进行了宏观理解--递归是将问题化为更小问题的子过程.这一节我们对在4.1节中递归在数组中的应用和4.2节中递归在链表中的应用进行微观解读: 一.关于4.1节中递归在数组中的应用 1) 我们先来看看4.1节中的代码实现,如下图: 为了更好的进行分析,我们将上述代码的最后一句进行拆分,拆

  • Java递归基础与递归的宏观语意实例分析

    本文实例讲述了Java递归基础与递归的宏观语意.分享给大家供大家参考,具体如下: 1.什么是递归 本质上,将原来的问题,转化为更小的同一问题 2.例子分析 假设我们需要对数组进行求和操作(只是为了更好理解递归程序) 要求如下:求解从索引为0到n-1的数组元素和. 分析: 为了能求解从索引为0到n-1的数组元素和,可以分解为第0个数加上索引从1到n-1的数组元素和,如下: 此时求解索引从1到n-1的数组元素和的规模比求解从索引为0到n-1的数组元素和要少一个数以此类推,如下: ....... 最基

  • Java递归模糊查询文件实例代码

    目录 前言 Java递归模糊查询文件 总结 前言 在数据结构算法设计中,或者一个方法的具体实现的时候,有一种方法叫做"递归",这种方法在思想上并不是特别难,但是实现起来还是有一些需要注意的.虽然对于很多递归算法都可以由相应的循环迭代来代替,但是对于一些比较抽象复杂的算法不用递归很难理解与实现. Java递归模糊查询文件 字符串模糊查询 /** * 模糊查询 * @param str 需要查询的字符串 * @param part 部分 * @return true 代表查到的 false

  • 详解Java递归实现树形结构的两种方式

    目录 0.引言 1.数据准备 2.类型转化 3.递归实现方法 3.1.Java7及以下纯Java递归实现 3.2.Java8及以上借助lamda表达式实现 0.引言 在开发的过程中,很多业务场景需要一个树形结构的结果集进行前端展示,也可以理解为是一个无限父子结构,常见的有报表指标结构.菜单结构等.Java中递归实现树形结构的两种常见方式如下: Java7及以下纯Java递归实现 Java8及以上借助lamda表达式实现 1.数据准备 Java实体类NodePO对应数据库表 package com

  • java递归法求字符串逆序

    本文实例讲述了java递归法求字符串逆序的方法.分享给大家供大家参考.具体实现方法如下: public static String reverseString(String x) { if(x==null || x.length()<2) return x; return reverseString(x.substring(1,x.length()))+ x.charAt(0); } 希望本文所述对大家的java程序设计有所帮助.

  • Java递归读取文件例子_动力节点Java学院整理

    Java递归列出目录下全部文件 /** * 列出指定目录的全部内容 * */ import java.io.*; class Recursion{ public static void main(String[] args) { String fileName="D:"+File.separator; File f=new File(fileName); printFile(f); } public static void printFile(File f){ if(f!=null){

  • Java递归如何正确输出树形菜单

    本文实例为大家分享了java递归输出树形菜单的具体代码,供大家参考,具体内容如下 首先我们要建立树节点的类: package com.tree; public class Node { private Integer id; private Integer parentId; private String name; private String link; public Integer getId() { return id; } public void setId(Integer id) {

随机推荐