我对递归的认识

简介: <div class="markdown_views"><p>首先明确一点: <br>递归是不符合人自然的逻辑思维的,需要训练.</p><h2 id="1递归的例子">(1)递归的例子</h2><p><strong>求5的阶乘</strong></p><pre class="prettyprint"><code class="language-java hl

首先明确一点:
递归是不符合人自然的逻辑思维的,需要训练.

(1)递归的例子

求5的阶乘

/***
     * 阶乘
     * @param n
     * @return
     */
    public static int arrayArrange(int n){
        if(n<2){
            return 1;
        }else{
            return n*arrayArrange(n-1);
        }
    }

arrayArrange方法体中调用了自身,只是参数不同.

求1到100的和

public static int getSum(int n){
        if(n<2){
            return 1;
        }else{
            return n+getSum(n-1);
        }
    }
    @Test
    public void test_getSum(){
        int n=10;
        System.out.println(getSum(n));
    }

获取指定目录下的所有的文件(不包括文件夹)

/***
     * 获取指定目录下的所有的文件(不包括文件夹),采用了递归
     * 
     * @param obj
     * @return
     */
    public static List<File> getListFiles(Object obj) {
        File directory = null;
        if (obj instanceof File) {
            directory = (File) obj;
        } else {
            directory = new File(obj.toString());
        }
        ArrayList<File> files = new ArrayList<File>();
        if (directory.isFile()) {
            files.add(directory);
            return files;
        } else if (directory.isDirectory()) {
            File[] fileArr = directory.listFiles();
            if(!ValueWidget.isNullOrEmpty(fileArr)){
                for (int i = 0; i < fileArr.length; i++) {
                    File fileOne = fileArr[i];
                    files.addAll(getListFiles(fileOne));
                }
            }
        }
        return files;
    }

级联删除文件

/***
     * delete a directory/folder<br>
     * 采用了递归
     * @param someFile
     *            :directory
     */
    public static boolean deleteDir(File someFile) {
        if (!someFile.exists()) {
            System.out.println("[deleteDir]File " + someFile.getAbsolutePath()
                    + " does not exist.");
            return false;
        }
        if (someFile.isDirectory()) {// is a folder
            File[] files = someFile.listFiles();
            if (!ValueWidget.isNullOrEmpty(files)) {
                for (File subFile : files) {
                    boolean isSuccess = deleteDir(subFile);
                    if (!isSuccess) {
                        return isSuccess;
                    }
                }
            }

        } else {// is a regular file
            boolean isSuccess = someFile.delete();
            if (!isSuccess) {
                return isSuccess;
            }
        }
        return !someFile.isDirectory() || someFile.delete();
    }

(2)递归的特征

(a)方法体中调用方法自身.拿累加举例说明
累加
getSum方法体中又调用了getSum,并且参数列表是完全一样的.

(b)每次调用参数都会有变化,至少有一个参数充当迭代器,类似于for循环的迭代器.

(c)一定有一个出口,要不然就死循环了.
这里的出口就是n<2的if条件分支.

(d)可以分解出来n个步骤,每个步骤的操作完全一样,只是参数不同而已.
n的累加等于n加上(n-1)的累加
(n-1)的累加等于(n-1)加上(n-2)的累加
(n-2)的累加等于(n-2)加上(n-3)的累加
(n-3)的累加等于(n-3)加上(n-4)的累加
……
每个步骤的操作都是”加上”.
当然有的递归,其操作可能复杂一些.
比如求组合:
求组合
组合

(3)递归使用的场景

哪些场景适用于递归呢?
(a)计算的次数与参数的规模成正相关
即参数越大,计算的次数越多
(b)每一步计算的规则完全一样,只是参数不同而已.
(c)后一次的计算结果依赖上一次的计算结果

(4)动态规划

说到递归,不得不说动态规划
(待续…)

(5)递归可以用for循环来代替吗?

哪些递归可以用for循环代替?
可以确定循环次数的
比如求累加

public static int getSum(int n){
        int sum=0;
        for(int i=0;i<n;i++){
            sum=sum+(i+1);
        }
        return sum;
    }

阶乘:

/***
     * 阶乘
     * @param n
     * @return
     */
    public static int arrayArrange(int n){
        int power=1;
        for(int i=0;i<n;i++){
            power=power*(i+1);
        }
        return power;
    }
    @Test
    public void test_arrayArrange2(){
        int n=4;
        System.out.println(arrayArrange(n));
    }

(6)回答网上一个递归的问题

问题见:递归调用中不明白的地方
我把问题翻译成为java:

public static void main(String[] args) {
        up(1);
    }
    public static void up(int n)
    {
        System.out.println(String.format("rank1 %d", n ));
        if (n < 4)    
            up(n+1);
        System.out.println(String.format("rank2 %d", n) );
    }

题主的问题:
不明白的地方就是:程序不能直接返回到main()中的初始调用部分吗?是因为递归的存在而导致的每一级逐步返回吗?为什么会出现4–>1的输出呢
程序的输出是:
输出
如果我是刚参加工作那会儿,也会不明白.
我们可以想象成中断处理程序
中断处理
递归调用
递归调用是多次执行一个函数,也就是多次将一个函数压栈,请注意,这里是将整个完整的函数压栈,而栈是一个先入先出的数据结构。递归的本质其实都可以用for循环来替代。在你的代码中,递归调用函数的顺序,也就是压栈的操作是up1,up2,up3,up4.而up2的调用时间是在up1内,up3得调用时间在up2内,up4得调用在up3内,所以up1得函数是在up2出栈以后才出栈,up2是在up3出栈以后才出栈,up3是在up4出栈以后才出栈。这样推一下,你就清楚函数的执行顺序和先后出栈顺序啦!
作者:hw1287789687
联系邮箱:1287789687@qq.com

相关文章
|
5月前
|
存储
【递归知识+练习】
【递归知识+练习】
42 0
|
6月前
C 递归
C 递归。
20 2
|
8月前
递归
递归
34 0
|
9月前
|
存储 算法 C++
递归的应用
递归的应用
|
10月前
|
算法 Python
递归的使用
递归的使用
32 0
|
11月前
|
机器学习/深度学习 BI
递归问题
递归问题
|
机器学习/深度学习
什么是递归
通过阶乘函数f(n)=n! f(0)=1 f(n)=f(n-1)*n(n>=1)简要理解递归
74 0
|
算法 索引
第 6 章 递归
简单的说: 递归就是方法自己调用自己,每次调用时传入不同的变量,递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。
52 0
|
存储 Serverless 开发者
递归的理解与实现
递归的理解与实现
递归的理解与实现

热门文章

最新文章