递归(recursion)

人分两种:男人和女人;算法分两种:递归的和迭代/循环的;递归是指用自己的较简单的情形定义自己

在数学和计算机科学中,递归是一种思路和策略,可以用于术语的定义(什么是表达式)问题的描述问题求解。用于问题求解的递归称为递归法。

有一个故事。物理学家计算10!时会说,“看,它等于1*2*~*10,即3628800”;数学家则说:“哦,10的阶乘,它等于10乘以9!”。

递归算法“轻率地”认为自己的较简单的情形是已知的。既然fact(n-1)是已知的,因而fact(n) 可求。这样“轻率”对理解递归概念至关重要。递归法不直接解决问题,而是将问题变成一个趋向递归出口的问题。使用递归方法需要存在一个基准情形,以避免无限循环(狗追自己的尾巴)。

package algorithm.recursion;
public class RecursionDemo{
    /**
     * 递归求Fibonacci级数的第n个元素,n基于1的自然数。
     */
    public static int fibonacc(int n){
        if(n<=1) return n;
        else return fibonacc(n-1)+fibonacc(n-2);
    }

    /**
     * 迭代求Fibonacci级数的第n个元素,n基于1的自然数。
     */
    public static int fibonacc1(int n){
        int first , second ,result ;
        first =second=result= 1;
        for(int i=3;i<=n ;i++){
            result = first + second;
            first = second;
            second =result;
        }
        return result;
    }
}

大多数情况下,迭代法和递归法能够相互转化。

使用递归法有2条实践准则:

1、设计优先。在任何情况下都可以采用递归法,简洁而清晰的程序设计优先。某些问题,例如那些需要后退的问题(如找出迷宫的出路、对树的一些操作),如果不采用递归则很难解决。

2、效率平衡。如果递归调用中出现重复性工作,改用循环。对于一般的数值计算,递归法通常不合适。

Java递归方法是通过方法调用栈实现的。在BlueJ中设置断点运行factorial (5),将显示方法调用情况。它仅仅“轻率地认为”factorial (4)已知,依此类推。到factorial (5),目前没有进行任一乘法计算。方法调用栈中有6个栈帧,顶层将计算factorial (0)。递归的方法的两个阶段是递推和回归

例如使用递归式sum(n) =n + sum(n-1),yqj2065看见过一个趣题。

    static long sum1(long a) {
        return (a == 1)? 1:(a + sum1(a - 1));
    }
    static long sum2(long a) {
        return (a == 1)? 1:(sum2(a - 1) + a);
    }

两者有区别吗?


汉诺塔

汉诺塔问题(Hanoi Tower problem):有三根杆子A、B、C,A杆上串有上小下大若干碟子。每次移动一块碟子,在确保小碟子只能叠在大碟子上面的条件下,利用B过渡,请把所有碟子从A杆移到C杆上。

对于具有递归思维的人,再多的碟子,也不过是两部分:上面的n-1个碟子被看成粘在一起的小碟子,而下面是一个大碟子。汉诺塔问题的递归算法:

结束条件: A杆上只有一个碟子,将它移到C。

递归式:

1、将上面的n-1个碟子从出发地A移到中转站B;

2、将第n个碟子移到目的地C;

3、将n-1个碟子从中转站B移到目的地C。

package algorithm.recursion;
public class HanoiTower{
    private static int step= 0;
    /**汉诺塔的递归演示。
     * @param from  碟子的出发地
     * @param temp  碟子的中转站
     * @param to   碟子的到达地
     * @param n  要移动的碟子个数
     */
    static void  hanoi(char from, char temp, char to, int n){
        if (n == 1) {
           step++;
           System.out.println("第"+step+ "步: "+ from+"→"+ to);
        }else {
            //将n-1个碟子移到中转站,故目前的到达地是temp。
            hanoi(from, to,temp,n-1);
            //第n个碟子移到到达地
            step++;
            System.out.println("第"+step+ "步: "+ from+"→"+ to);
            //将n-1个碟子移到到达地。
            hanoi(temp,from,to,n-1);
        }
    }
}

hanoi(‘A’, ‘B’, ‘C’, 3)的输出:

第1步: A→C

第2步: A→B

第3步: C→B

第4步: A→C

第5步: B→A

第6步: B→C

第7步: A→C

汉诺塔问题的迭代算法比较复杂,

时间: 2024-08-06 03:46:26

递归(recursion)的相关文章

数据结构与算法5: 递归(Recursion)

数据结构与算法5: 递归(Recursion) 写在前面 <软件随想录:程序员部落酋长Joel谈软件>一书中<学校只教java的危险性>一章提到,大学计算机系专业课有两个传统的知识点,但许多人从来都没搞懂过,那就是指针和递归.我也很遗憾没能早点熟练掌握这两个知识点.本节一些关键知识点和部分例子,都整理自教材或者网络,参考资料列在末尾.如果错误请纠正我. 思考列表: 1)什么程序具有递归解决的潜质? 2)递归还是非递归算法,怎么选择? 3)递归程序构造的一般模式 1.递归定义 首要引

Atitit &#160;循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate).

Atitit  循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate). 1.1. 循环算是最基础的概念, 凡是重复执行一段代码, 都可以称之为循环. 大部分的递归, 遍历, 迭代, 都是循环.1 1.2. 递归的定义是, 根据一种(几种)基本情况定义的算法, 其他复杂情况都可以被逐步还原为基本情况.1 1.3. 递归的基本概念和特点1 1.4. 迭代(数学): 在循环的基础上, 每一次循环, 都比上一次更为接近结果.2 1.5. 编程语言中的循环

递归Recursion举例

#GCD最大公约数 1 //求a和b的最大公约数 2 int GCD(int a, int b) 3 { 4 if (a % b == 0) 5 return b; 6 else 7 return GCD(b, a % b); 8 } #翻转字符串 1 string reverseString(string str) 2 { 3 if (str.length() == 0) 4 return ""; 5 else 6 return reverseString(str.substr(1)

递归Recursion

从开始自学写代码开始,就感觉递归是个特别美丽的算法. “如果使用循环,程序的性能可能更高:如果使用递归,程序可能更容易理解.如何选择要看什么对你来说更重要.” 编写递归函数时,必须告诉它何时停止递归.因此,每个递归函数都有两部分:基线条件(base case)和递归条件(recursive case).递归条件指的是函数调用自己,基线条件则指的是函数不再调用自己,从而避免形成无限循环. 编写涉及数组的递归函数时,基线条件通常是数组为空或只包含一个元素.陷入困境时,请检查基线条件是不是这样的. 例

Python算法:推导、递归和规约

Python算法:推导.递归和规约 注:本节中我给定下面三个重要词汇的中文翻译分别是:Induction(推导).Recursion(递归)和Reduction(规约) 本节主要介绍算法设计的三个核心知识:Induction(推导).Recursion(递归)和Reduction(规约),这是原书的重点和难点部分 正如标题所示,本节主要介绍下面三部分内容: • Reduction means transforming one problem to another. We normally red

递归程序设计

一般定义: 程序调用自身的编程技巧称为递归(recursion). 递归做为一种算法设计技巧,是指函数/过程/子程序在运行过程中直接或间接调用自身而产生的重入现象. 递归过程总是一个过程还未执行完就执行另一个过程(但是执行另一过程前会保存未执行完时候的变量值),如此反复,一直执行到边界条件,执行完余下的过程后,返回上一次未执行完的过程执行(此时使用的是当时的变量),如此反复,直到回到起始位置. 设计递归程序的基本思路: 1.先弄清楚递归的顺序.在递归的实现中,往往需要假设后续的调用已经完成,在此

递归解决换零钱问题--回顾总结之递归的表达能力

前面为了保持叙述的流畅,没有做太多的引申,把总结推迟到了后面. 补上一些总结,以防止出现"下面呢?下面没有了"的尴尬. 方向性问题 虽然题目在一开始就暗示了这一点,但首先,我们还是要问,它能用递归解决吗? 有点怀疑精神是好的,既要低头走路,更要抬头看路,以防止发生方向性错误,导致缘木求鱼的后果. 说这个问题能用递归解决,这种信心或者判断的依据来自于哪呢? 有人可能知道了,换零钱这个问题在<计算机程序的构造和解释>(SICP:Structure and Interpretat

算法设计方法:递归的内涵与经典应用

摘要: 大师 L. Peter Deutsch 说过:To Iterate is Human, to Recurse, Divine.中文译为:人理解迭代,神理解递归.毋庸置疑地,递归确实是一个奇妙的思维方式.对一些简单的递归问题,我们总是惊叹于递归描述问题的能力和编写代码的简洁,但要想真正领悟递归的精髓.灵活地运用递归思想来解决问题却并不是一件容易的事情.本文剖析了递归的思想内涵,分析了递归与循环的联系与区别,给出了递归的应用场景和一些典型应用,并利用递归和非递归的方式解决了包括阶乘.斐波那契

递归趣文

公认的递归(Recursion)的标准定义是非常难理解的:若一个对象部分地包含它自己,或用它自己给自己定义,则称这个对象是递归的:若一个过程直接地或间接地调用自己,则称这个过程是递归的过程.    递归一词很少有过专业的定义,因此本文不在于去解释上一段文字的意义.虽然概念抽象,但递归其本身是不难理解的.通过本文的介绍,读者不一定能深入了解递归,只要能通过具体的例子模模糊糊地知道一些递归的思想和用途就可以了.    究竟什么是递归呢?其实,递归就是大鱼吃小鱼,就是一条蛇咬住自己的尾巴.递归是指一样