关于递归的一些思考

说到递归,咱们张嘴就能说出来是什么?本身调用本身。官方点说就是一个函数用它本身来定义时就是递归。
有时候不少的数学问题或者生活中的问题均可以使用计算机程序来解决,把这些问题统计起来,找出他们之间的规律,得出一个计算公式,用程序来计算这个公式得出结果。梦想老是美好的,有时候咱们得出的公式有些是以不太标准的形式定义的。 css

例如斐波那契数列,经过分析咱们获得一个公式,它知足:算法

F(0)=0  
                                F(1)=1
                                F(2)=1

                        F(n)=F(n-1)+F(n-2)(n>=2)

在上面的公式定义中咱们发现F(0)=0,F(1)=1,F(2)=1
利用递归咱们能够很方便的获得解决这个问题的方法,程序以下:markdown

public int getFib(int n) {
        if (n < 0) {
            return -1;
        } else if (n == 0) {
            return 0;
        } else if (n == 1 || n == 2) {
            return 1;
        } else {
            return getFib(n - 1) + getFib(n - 2);
        }
    }

上面的程序中两个else if用于处理基准状况,何为基准状况?就是函数的值不须要递归计算直接能够得出的结果。一个递归函数必须有基准状况(不须要递归计算就能够获得的结果),没有基准状况的递归方法没有意义。
试着想想:咱们如今要利用上面的程序计算出F(3)的结果是多少?咱们发现若是要算F(3)就要知道F(2)和F(1)的值,咱们发现F(2)和F(1)的值已经知道了,那么F(3)的结果很容易获得。咱们先忘记上面的状况,假如如今咱们要计算F(5),根据公式计算F(5)就要知道F(4)和F(3),可是F(4)和F(3)咱们不知道,可是能够根据公式算出来,F(4)=F(3)加上F(2),F(3)=F(2)加上F(1),综上所述之后的每个结果都是根据咱们已知的结果算出来的
在上面的程序中两个else if给出了基准因此咱们后面的递归计算才能够获得。
上面的推倒结果的过程能够发现递归就是一个循环推理的过程。
仍是这个基准的问题,求结果当咱们想要求F(1)的时候,若是没有基准,求F(1)就要知道F(0)和F(-1),而后F(0)又要依赖F(-1)和F(-2),这样一直向下计算,永远不能算出结果,显然这是一个错误的程序,这样的结果就是计算机的资源所有都在计算这些没有意义的计算,包括跟踪挂起的函数调用以及他们的变量记录工做都要计算机来完成。因此咱们在方法的最开始规定了参数不能小于0。 数据结构

前面的论述基本上讨论了递归的两个基本准则:
* 基准准则:就像一个开口,不用递归就能够获得的结果
* 不断推动:须要递归求的计算,递归的方向老是朝着基准的方向推动 函数

书上有一个很好的例子助于理解,遇到一个不认识的词语咱们要查字典,咱们根据下面的解释理解这个词语的意思,可是这段解释中咱们又遇到了不认识的词语,咱们又要接着查,就这样一直查,直到咱们找到了一处咱们理解的词语(就是上面说的基准)以前全部的也就理解了。这个查询过程也就结束了。 spa

在设计递归函数的时候咱们假设全部的递归都能运行。当递归程序运行起来想要追踪具体的调用关系是很困难的。
记住要有基准,每次递归朝着基准前进 设计


这篇文章根据《数据结构与算法分析》写出,有书上的,也有个人理解,初读这本书感受真的不同,字多,书上好多的知识解释的很详细,建议认真阅读!作笔记!我从前对递归的理解就是一句话,总结了以后原来递归的知识能够有这么多。code