JavaSE第八十八讲:递归详解以及递归在阶乘与斐波那契数列的使用
2013-01-19 22:52
399 查看
1. 递归(Recursion)
所谓递归(Recursion),就是方法调用自身。对于递归来说,一定有一个出口,让递归结束,只有这样才能保证不出现死循环。
对于递归来说,调试起来也是比较麻烦的,因为递归是自己在调用自己。每一次调用都要再自己的方法里面找出它们的规律
2. 递归在阶乘中的运用
120
120
【程序说明】:
阶乘:n! = n * (n - 1) * (n - 2) * ... * 2 * 1
等价:n! = n * (n - 1)!
-------------->(1式计算n!必须知道(n-1)!)
同理:(n - 1)! = (n - 1) * (n - 2)! ------>(计算(n-1)!必须知道(n-2)!)
...
所以如此重复相同算法,计算的过程是一样的,一直到计算1的继承为止。
上式1也可以写成函数形式:f(x) = n * f(x - 1)
【调用】上述程序中整个递归的调用过程如下:
5 * compute2(4)
4 * compute2(3)
3 * compute2(2)
2 * compute2(1)
【返回】此时number为1程序返回1后程序返回的过程如下:
2 * 1
3 * 2 * 1
4 * 3 * 2 * 1
5 *4
* 3 * 2 * 1
所以输出结果为120
3. 递归在斐波那契数列中的运用
斐波纳契数列,又称黄金分割数列,指的是这样一个数列:1、1、2、3、5、8、13、21、……
在数学上,斐波纳契数列以如下被以递归的方法定义:F0 = 0,F1 = 1,Fn
= F(n - 1) + F(n - 2)(n>=2,n∈N*)
上面的数列中,要求出一个值必然是要知道前面一个和前面第二个的值。当推到第一个或者第二个数字是1的时候,则为递归出口。
程序如下:
package com.ahuier.io;
/*
* 递归解斐波那契数列:1、1、2、3、5、8、13、21......
*/
public class Fab {
//n 表示数列中第几个数字
public int compute(int n){
//递归出口
if(n == 1 || n == 2){
return 1;
}
else{
//对于斐波那契数列中的第三个或者第三个以上的任意数字的值等于前两个值的和
return compute(n - 1) + compute(n - 2);
}
}
public static void main(String[] args) {
Fab fab = new Fab();
System.out.println(fab.compute(9));
}
}
编译执行结果:
34
【说明】:递归的难主要是难在他的思想上。
3. 递归在File类中的使用
在上一讲中,我们知道了File类的基本使用方法,其中有一个是delete()删除一个目录或者文件的方法,这边要注意的是delete()方法删除目录的时候,如果目录里面包含了目录或者文件,则这个目录是删不掉的。
查看JDK Doc文档中的File类delete()使用方法。
对于一个有包含目录和文件的目录来说,要想删除这个目录,则首先要检查这个目录里面是否有文件,如果有文件,则将所有的文件删掉,然后再把自身删除,如果这个目录里面除了包含文件外还有其他的目录,同样也是先把这些目录底下的文件全部删除,再删除自身,然后退到上一级再进行同样的删除操作。这其实是一个递归的过程。
写一个程序,删除一个目录下的所有目录和文件。
package com.ahuier.io;
import java.io.File;
/*
* 删除指定目录下的所有子目录或者文件
* 注意这个程序的实现只有通过递归才能实现的,其他的方法是实现不了的。
*/
public class FileTest9 {
public static void deleteAll(File file){
/*
* 递归的出口点:
* 第一个返回点是:如果待删除的目标file是一个真正的文件,直接删掉
* 第二个返回点是:如果目标是一个目录,这个目录是空的,直接删掉
*/
if(file.isFile() || file.list().length == 0){
file.delete();
}
else{
File[] files = file.listFiles(); //要删除这个目录,必须先删除目录底下的内容,所以先获得了待删除的目录内容
//遍历这个目录
for(File f : files){
deleteAll(f); //如果这个目录里面还有目录,则同样执行这个方法,表示删除这个目录,先删除该目录底下的内容
f.delete(); //然后再删除自己
}
}
}
public static void main(String[] args) {
deleteAll(new File("C:/abc"));
}
}
编译执行后删除目录"C:/abc"下的所有内容。
4. 递归作业:给定任意一个目录,以树形方式展现出该目录中的所有子目录和文件。另外,在展现的时候将目录排在上面,文件排在下面。每一层要加上缩进。
所谓递归(Recursion),就是方法调用自身。对于递归来说,一定有一个出口,让递归结束,只有这样才能保证不出现死循环。
对于递归来说,调试起来也是比较麻烦的,因为递归是自己在调用自己。每一次调用都要再自己的方法里面找出它们的规律
2. 递归在阶乘中的运用
package com.ahuier.io; public class Test1 { //循环方式计算机阶乘,又叫做迭代的方式 public int compute(int number){ int result = 1; for(int i = number; i > 0; i--){ result = result * i; } return result; } //使用递归方式计算机阶乘 public int compute2(int number){ //递归出口,当number等于1时 if(1 == number){ return 1; } else{ return number * compute2(number - 1); } } public static void main(String[] args){ Test1 test = new Test1(); System.out.println(test.compute(5)); System.out.println(test.compute2(5)); } }编译执行结果:
120
120
【程序说明】:
阶乘:n! = n * (n - 1) * (n - 2) * ... * 2 * 1
等价:n! = n * (n - 1)!
-------------->(1式计算n!必须知道(n-1)!)
同理:(n - 1)! = (n - 1) * (n - 2)! ------>(计算(n-1)!必须知道(n-2)!)
...
所以如此重复相同算法,计算的过程是一样的,一直到计算1的继承为止。
上式1也可以写成函数形式:f(x) = n * f(x - 1)
【调用】上述程序中整个递归的调用过程如下:
5 * compute2(4)
4 * compute2(3)
3 * compute2(2)
2 * compute2(1)
【返回】此时number为1程序返回1后程序返回的过程如下:
2 * 1
3 * 2 * 1
4 * 3 * 2 * 1
5 *4
* 3 * 2 * 1
所以输出结果为120
3. 递归在斐波那契数列中的运用
斐波纳契数列,又称黄金分割数列,指的是这样一个数列:1、1、2、3、5、8、13、21、……
在数学上,斐波纳契数列以如下被以递归的方法定义:F0 = 0,F1 = 1,Fn
= F(n - 1) + F(n - 2)(n>=2,n∈N*)
上面的数列中,要求出一个值必然是要知道前面一个和前面第二个的值。当推到第一个或者第二个数字是1的时候,则为递归出口。
程序如下:
package com.ahuier.io;
/*
* 递归解斐波那契数列:1、1、2、3、5、8、13、21......
*/
public class Fab {
//n 表示数列中第几个数字
public int compute(int n){
//递归出口
if(n == 1 || n == 2){
return 1;
}
else{
//对于斐波那契数列中的第三个或者第三个以上的任意数字的值等于前两个值的和
return compute(n - 1) + compute(n - 2);
}
}
public static void main(String[] args) {
Fab fab = new Fab();
System.out.println(fab.compute(9));
}
}
编译执行结果:
34
【说明】:递归的难主要是难在他的思想上。
3. 递归在File类中的使用
在上一讲中,我们知道了File类的基本使用方法,其中有一个是delete()删除一个目录或者文件的方法,这边要注意的是delete()方法删除目录的时候,如果目录里面包含了目录或者文件,则这个目录是删不掉的。
查看JDK Doc文档中的File类delete()使用方法。
对于一个有包含目录和文件的目录来说,要想删除这个目录,则首先要检查这个目录里面是否有文件,如果有文件,则将所有的文件删掉,然后再把自身删除,如果这个目录里面除了包含文件外还有其他的目录,同样也是先把这些目录底下的文件全部删除,再删除自身,然后退到上一级再进行同样的删除操作。这其实是一个递归的过程。
写一个程序,删除一个目录下的所有目录和文件。
package com.ahuier.io;
import java.io.File;
/*
* 删除指定目录下的所有子目录或者文件
* 注意这个程序的实现只有通过递归才能实现的,其他的方法是实现不了的。
*/
public class FileTest9 {
public static void deleteAll(File file){
/*
* 递归的出口点:
* 第一个返回点是:如果待删除的目标file是一个真正的文件,直接删掉
* 第二个返回点是:如果目标是一个目录,这个目录是空的,直接删掉
*/
if(file.isFile() || file.list().length == 0){
file.delete();
}
else{
File[] files = file.listFiles(); //要删除这个目录,必须先删除目录底下的内容,所以先获得了待删除的目录内容
//遍历这个目录
for(File f : files){
deleteAll(f); //如果这个目录里面还有目录,则同样执行这个方法,表示删除这个目录,先删除该目录底下的内容
f.delete(); //然后再删除自己
}
}
}
public static void main(String[] args) {
deleteAll(new File("C:/abc"));
}
}
编译执行后删除目录"C:/abc"下的所有内容。
4. 递归作业:给定任意一个目录,以树形方式展现出该目录中的所有子目录和文件。另外,在展现的时候将目录排在上面,文件排在下面。每一层要加上缩进。
相关文章推荐
- 详解python使用递归、尾递归、循环三种方式实现斐波那契数列
- 编译运行内核里面的helloworld以及使用递归计算阶乘
- android shape的使用详解以及常用效果(渐变色、分割线、边框、半透明阴影效果等)
- apache的AllowOverride以及Options使用详解
- java算法 使用递归计算阶乘
- JAVAWEB开发之Hibernate详解(一)——Hibernate的框架概述、开发流程、CURD操作和核心配置与API以及Hibernate日志的使用
- WebService里的wsdl的详解以及使用注解修改wsdl的配置
- dos命令之 set (显示、设置或删除 cmd.exe 环境变量) 用法详解以及使用变量
- 【好】C++中lib 和 dll 的区别、生成以及使用详解
- Memcached常用命令以及使用说明详解
- [算法]贪心算法的详解以及使用
- 详解head头标签元素的意义以及使用场景
- Linux 安装以及基本使用Hadoop 详解
- JAVAWEB开发之mybatis详解(一)——mybatis的入门(实现增删改查操作)、自定义别名、抽取代码块以及动态SQL的使用
- 【React Native开发】React Native控件之WebView组件详解以及实例使用(22)
- PopupWindow的使用以及ArrayAdatper.notifyDataSetChanged()无效详解
- GIT教程 — 详解本地库的使用以及原理(二)
- php array_slice函数的使用以及参数详解
- Python 使用递归斐波那契数列
- #ifndef/#define/#endif以及#if defined/#else/#endif使用详解