java 递归深入理解_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
} 

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索java
递归
深入理解递归、java递归怎么理解、深入理解java虚拟机、深入理解java7、深入理解java泛型详解,以便于您获取更多的相关知识。

时间: 2024-09-24 06:54:39

java 递归深入理解_java的相关文章

Java中的迭代和递归详解_java

前言 最近在看书的时候看到这一内容,感觉还是蛮有收获的.迭代使用的是循环(for,while,do...wile)或者迭代器,当循环条件不满足时退出.而递归,一般是函数递归,可以是自身调用自身,也可以是非直接调用,即方法A调用方法B,而方法B反过来调用方法A,递归退出的条件为if,else语句,当条件符合基的时候退出. 上面是迭代和递归的语法特性,他们在Java中有什么不同呢?下面通过这篇文章来详细了解了解. 一.递归 提到迭代,不得不提一个数学表达式: n!=n*(n-1)*(n-2)*...

浅谈Java 对于继承的初级理解_java

概念:继承,是指一个类的定义可以基于另外一个已存在的类,即子类继承父类,从而实现父类的代码的重用.两个类的关系:父类一般具有各个子类共性的特征,而子类可以增加一些更具个性的方法.类的继承具有传递性,即子类还可以继续派生子类,位于上层的类概念更加抽象,位于下层的类的概念更加具体. 1.定义子类: 语法格式 [修饰符] class 子类名 extends 父类名{ 子类体 } 修饰符:public private protected default 子类体是子类在继承父类的内容基础上添加的新的特有内

Java递归遍历树形结构_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类和对象_java

面向对象的程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分.在面向对象程序设计(OOP)中,不必关心对象的具体实现.在传统的结构化程序设计中,算法是第一位的,数据结构是第二位的,即首先确定如何操作数,再考虑如何组织数据,以方便操作.而OOP则颠倒了这种次序,将数据放在第一位,然后再考虑操作数据的算法. 一.类 类是构造对象的模板和蓝图.通俗地说,类相当于建筑的图纸,而对象相当于建筑物.由类构造对象的过程称为创建对象的实例. Java中通过关键字class定义"类"

初步理解Java的泛型特性_java

在Java SE1.5中,增加了一个新的特性:泛型(日本语中的总称型).何谓泛型呢?通俗的说,就是泛泛的指定对象所操作的类型,而不像常规方式一样使用某种固定的类型去指定.泛型的本质就是将所操作的数据类型参数化,也就是说,该数据类型被指定为一个参数.这种参数类型可以使用在类.接口以及方法定义中.  一.为什么使用泛型呢?     在以往的J2SE中,没有泛型的情况下,通常是使用Object类型来进行多种类型数据的操作.这个时候操作最多的就是针对该Object进行数据的强制转换,而这种转换是基于开发

java递归法求字符串逆序_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递归原理求高人解惑 int i=1;int Test(int n){ System.out.println(""*****************""+(i++)); int result =0; if(n==1) return 1; result = Test(n-1)*n; System.out.println(result+"" ""+n); return result;}我进行调试,比如n=8,只打印

java递归 if() return返回到哪里?

问题描述 java递归 if() return返回到哪里? 学习归并排序时,遇到递归的思想.测试输入 mergesortexample单步调试到,if (hi<=lo) return;当hi=0,lo=0时,执行return,在我理解中,return就是退出方法了,为何会跳到 sort(amid+1hi);而且此时,lo=0,hi=1? private static void sort(Comparable[] aint loint hi){ //将数组a[lo hi]排序 if (hi<=l

在循环内部调用递归怎么理解,求解答

问题描述 在循环内部调用递归怎么理解,求解答 private void tree(Set articles,Connection conn,int id,int grade){ String sql="select * from article where pid="+id; Statement stmt=DB.createStmt(conn); ResultSet rs=DB.executQuery(stmt, sql); try{ while(rs.next()){ Article