java算法1_递归

递归:方法内部调用方法本身的一种编程技巧。

当一个方法(功能)被重复使用时,如果每一次使用该方法参数都不确定,都是由上次的方法返回的结果来确定的,这个时候就要使用递归。

比如:N 的阶乘:

package edu.aiai.coll;
import java.util.Scanner;
public class TestRec {
    public static void main(String[] args) {
        System.out.println(fac((new Scanner(System.in)).nextInt()));
    }
    public static int fac(int n){
        if(n==1){
            return 1;
        }else{
            return n*fac(n-1);
        }
    }
}

注意点:

1递归必须有明确的出口(如上面代码中的n等于1时的返回1),不然就会一直递归下去,直到程序报StackOverflowError错误而终止。

2递归调用中各层的执行顺序问题:最外层调用内层调用最内层,等最内层执行完毕之后,内层执行,然后最外层执行并返回结果,以上面为例:如果计算4的阶乘,是先算3的阶乘,要想算3的阶乘,先算2的阶乘,想算2的阶乘,先算1的阶乘,1的阶乘返回1fac(2)拿到1之后执行2乘以1,返回2,2的阶乘计算完毕,然后是3的阶乘,最后是4的阶乘,返回结果,即为我们想要的结果。

按照上面说的执行过程来看一个文件递归删除的例子:

package edu.aiai.coll;
import java.io.File;
public class TestRec {
    public static void main(String[] args) {
        File dir = new File("d:/test");
        delDir(dir);
    }
    public static void delDir(File dir){
        File[] arrFiles = dir.listFiles();
        for(int i=0;i<arrFiles.length;i++){
            if(arrFiles[i].isDirectory()){
                delDir(arrFiles[i]);
            }
            arrFiles[i].delete();
            System.out.println(arrFiles[i]);
        }
        dir.delete();
    }
}

输出结果为

d:\test\java\javaSE\BubbleTest.class

d:\test\java\javaSE

d:\test\java\NewFile.xml

d:\test\java\question\api\allclasses-frame.html

d:\test\java\question\api\resources\inherit.gif

d:\test\java\question\api\resources

d:\test\java\question\api

d:\test\java\question\Num01.class

d:\test\java\question

d:\test\java

可以看出,执行过程为:找的时候逐层向里面找,执行的时候最里面先执行然后外面依次执行,最后是最外面执行。

200331618.jpg

上图简单画出了执行顺序,和上面文字描述一致。

递归另一个需要注意的问题是不要多(>1)处递归,这样会验证降低效率:

比如菲波那契数列:

package edu.aiai.coll;
public class TestRec {
    public static void main(String[] args) {
        System.out.println(f(10));
    }
    public static int f(int n){
        if(n==1 || n==2){
            return 1;
        }
        return f(n-1)+f(n-2);
    }
}

效率低下原因如下图:以9为例:

200608302.jpg

想得到f(9)的值,就得先算f(8)f(7),想得到f(8)的值,就得先算f(7)f(6),依次类推,运算的次数呈几何级数增长,所以如果数大的话,计算效率会非常低。

这个我们可以通过循环叠加的方法解决:

long n1=1, n2=1;
for(int i=3; i<=50; i++){
    n2 = n1+n2;
    n1 = n2-n1;
}

再说一个著名的递归调用的问题:汉诺塔 Towers of Hanoi

package com.anjoyo.hanoi;
import java.util.Scanner;
public class TestHanoi {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        System.out.println("请输入盘子数量:");
        int niNum = scan.nextInt();
        move(niNum,'A','B','C');
    }
    public static void move(int n,char a,char b,char c){
        if(n==1){
            System.out.println("盘 " + n + " 由 " + a + " 移至 " + c);
        }else{
            move(n - 1, a, c, b);
            System.out.println("盘 " + n + " 由 " + a + " 移至 " + c);
            move(n - 1, b, a, c);
        }
    }
}

关于汉诺塔,这里再上传一个ppt,帮助大家理解。


你可能感兴趣的:(java,算法,递归)