递归浅析

        递归算法是一种直接或者间接地调用自身算法的过程。在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解。
递归算法解决问题的特点:
(1) 递归就是在过程或函数里调用自身。
(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
(3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
(4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。       
        递归算法所体现的“重复”一般有三个要求:
一是每次调用在规模上都有所缩小(通常是减半);
二是相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入);
三是在问题的规模极小时必须用直接给出解答而不再进行递归调用,因而每次递归调用都是有条件的(以规模未达到直接解答的大小为条件),无条件递归调用将会成为死循环而不能正常结束。
        经典案例:

       1.阶乘的案例(求5!?)

publicclass Recursion {

    /**

     * 降阶

     * 5!=5*4!

     * 4!=4*3!

     * 3!=3*2!

     * 2!=2*1!

     * 1!=1;

     */

    staticint jieCheng(int n){             //假设n=1

        if(n<=1){

            return 1;

        }else{

            return n*jieCheng(n-1);        //假设2

        }  

}   

    publicstaticvoid main(String[] args) {

        System.out.println(jieCheng(3));

    }

}

             2.斐波那契数列

publicclass RecursionDemo1 {

    /**

     * f(1)=0;  1

     * f(2)=1;

     * f(3)=1;-f(2)+f(1)

     * f(4)=2;f(3)+f(2)

     * f(n)=; f(n-1)+f(n-2);

     *

     */

    staticint feiNa(int n){

        if(n==1){

            return 0;

        }elseif(n==2){

            return 1;

        }else{

            returnfeiNa(n-1)+feiNa(n-2);

        }

    }

    publicstaticvoid main(String[] args) {

        System.out.println(feiNa(4));

    }

}

3.斐波那契数列引发的兔子繁殖问题分析及实现

     兔子繁殖的问题:一般而言,兔子在出生两个月后, 就有繁殖能力, 一对兔子每个月能生出一对小兔子来 。如果所有兔子都不死,那么一年以后可以繁殖多少对兔子?

分析:

经过月数

0

1

2

3

4

5

6

7

8

9

10

11

12

幼仔对数

1

0

1

1

2

3

5

8

13

21

34

55

89

成兔对数

0

1

1

2

3

5

8

13

21

34

55

89

144

总体对数

1

1

2

3

5

8

13

21

34

55

89

144

233

import java.sql.Date;

publicclass RecursionDemo2 {

    /**

     * 幼崽 n代表月数

     *

     * @param n

     * @return

     */

    staticint feiNa(int n) { // 月数

        if (n == 0) {

            return 1;

        } elseif (n == 1) {

            return 0;

        } elseif (n == 2) {

            return 1;

        } elseif (n == 3) {

            return 1;

        } else {

            returnfeiNa(n - 1) +feiNa(n -2);

        }

    }

    /**

     * 成崽 n代表月数

     *

     * @param n

     * @return

     */

    staticint feiNas(int n) { // 月数

        if (n == 0) {

            return 0;

        } elseif (n == 1) {

            return 1;

        } else {

            returnfeiNas(n - 1) +feiNas(n- 2);

        }

    }

    /**

     * 总数n代表月数

     *

     * @param n

     * @return

     */

    staticint feiNass(int n) { // 月数

        if (n == 0) {

            return 1;

        } elseif (n == 1) {

            return 1;

        } else {

            returnfeiNass(n - 1) +feiNass(n- 2);

        }

    }

    publicstaticvoid main(String[] args) {

        System.out.println(feiNa(12));

        System.out.println(feiNas(12));

        System.out.println(feiNass(12));

        System.out.println(newDate(2,11, 1));

    }

 3汉诺塔问题

已知有三根针分别用1,2,3表示,在一号针中从小放n个盘子,现要求把所有的盘子
从1针全部移到3针,移动规则是:使用2针作为过度针,每次只移动一块盘子,且每根针上
不能出现大盘压小盘.找出移动次数最小的方案.
程序如下:
package test;

import java.util.*;

import javax.swing.text.html.HTMLDocument.Iterator;

public class Hanoi {

    // 塔
    class Tower<E> {
        // 塔编号
        private int number;
        // 塔名称
        private String name;
        // 存放盘子的栈
        private Stack<E> stack = new Stack<E>();

        public Tower(int number, String name) {
            this.number = number;
            this.name = name;
        }

        public int getNumber() {
            return number;
        }

        public String getName() {
            return name;
        }

        public Stack<E> getStack() {
            return stack;
        }

    }

    // 盘子
    class Tray {
        // 盘子编号
        private int number;
        // 盘子名称
        private String name;

        public Tray(int number, String name) {
            this.number = number;
            this.name = name;
        }

        public int getNumber() {
            return number;
        }

        public String getName() {
            return name;
        }

        public String toString() {
            return name;
        }
    }

    public <T> void hanoi(int num, Tower<T> from, Tower<T> middle, Tower<T> to) {
        if (num == 1) {
            move(from, middle, to);
        } else {
            // 将num-1个盘子从from塔上移到middle塔上
            hanoi(num - 1, from, to, middle);
            // 将第num个盘子移到to塔上
            move(from, middle, to);
            // 将num-1个盘子从middle塔上移到to塔上
            hanoi(num - 1, middle, from, to);
        }
    }

    private <E> void move(Tower<E> from, Tower<E> middle, Tower<E> to) {
        E tray = from.getStack().pop();
        to.getStack().push(tray);
        StringBuilder sb = new StringBuilder();
        sb.append("=====================Hanoi.move()======================\n")
                .append(" Move tray : ").append(((Tray) tray).getName())
                .append(" from ").append(from.getName()).append(" to ")
                .append(to.getName()).append("\n ").append(from.getName())
                .append(":").append(format(from)).append(",")
                .append(middle.getName()).append(":").append(format(middle))
                .append(",").append(to.getName()).append(":")
                .append(format(to));
        System.out.println(sb.toString());
    }

    private <E> String format(Tower<E> tower) {
        Iterator<E> i = tower.getStack().iterator();
        if (!i.hasNext())
            return "[]";
        StringBuilder sb = new StringBuilder();
        sb.append('[');
        while (i.hasNext()) {
            sb.append(i.next().toString()).append(",");
        }
        sb.replace(sb.length() - 1, sb.length(), "]");
        return sb.toString();
    }

    public static void main(String[] args) {
        Hanoi hanoi = new Hanoi();
        Tower<Tray> from = hanoi.new Tower<Tray>(1, "1号塔");
        Tower<Tray> middle = hanoi.new Tower<Tray>(2, "2号塔");
        Tower<Tray> to = hanoi.new Tower<Tray>(3, "3号塔");
        int num = 4;
        for (int i = num; i > 0; i--) {
            Tray tray = hanoi.new Tray(i, i + "号盘子");
            from.getStack().push(tray);
        }
        hanoi.hanoi(num, from, middle, to);
    }
}

另外,递归还有它很广泛的应用比如象棋游戏就可以用递归来写:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值