java递归算法(二) ——详解消除递归以及经典示例

消除递归

一个算法作为一个递归的方法通常的概念理解是很容易的,但是递归的使用在方法的调用和返回都会有额外的开销,通常情况下,用递归能实现的,用循环都可以实现,而且循环的效率更高,所以实际运用中,把递归算法转换为非递归算法是很有用的,这种转换通常会运用到栈,

递归和栈

递归和栈有着紧密的联系,而且大多数编译器都是用栈来实现递归的,当调用一个方式时,编译器会把这个方法的所有参数和返回地址都压入栈中,然后把控制转移给这个方法,当这个方法返回时,这些值退栈,参数消失,并且把控制权重新返回地址处。

  1. 当一个方法被调用时,他的参数和返回地址被压入一个栈中;
  2. 这个方法可以通过获取栈顶元素来访问它的参数;
  3. 当这个方法要返回时,它可以查看栈以获得返回地址,然后这个地址以及方法的所有参数退栈并且销毁。
有趣些兔子问题

题目是 :有一对兔子,小兔子长到第三个月后,每个月会生一堆兔子,加入兔子不死的话,问每个月兔子的总数是多少。
首先我们要明白题目的意思是指每个月的兔子的总数,假设将兔子氛围小中大三种,兔子出生后每三个月生一对兔子
那么我们假定第一个兔子为小兔子,第二个月的兔子为中兔子,第三个月为大兔子,那个第一个月分别是1,0,0,第二个月的是0,1,1
第三个月的事1,0,1第四个月是1,1,1第五个月的是2,1,2第六个月为3,2,3第七个月为5,2,5.。。。
兔子的总数分别是1,1,2,3,5,8,13,,,
于是得出了一个规律,从第三个月开始,侯曼的兔子都是前面两个的总数之和,这就是斐波那契数列。

递归实现

    @Test
    public void Digui() {
        int i = 1;
        for(i=1;i<=12;i++){
            System.out.println("兔子第"+i+"个月的总数为:"+f(i));
        }
    }

    public static int f(int x) {
        if (x == 1 || x == 2) {
            return 1;
        } else {
            return f(x - 1) + f(x - 2);//当前月的兔子的个数等于前两个月兔子的相加
        }
    }

输出
在这里插入图片描述

非递归方法实现
    @Test
    public void getRubbitNum() {
        int sun;//兔子每个月的总数
        int new_rubbit = 1;//兔子第一个月的数(循环中代表的是上个月的数据)
        int old_rubblt = 1;//兔子第二个月的数(循环中代表的是上上个月的数据)
        for (int i = 3; i <= 12; i++) {
//            上面我说过第三个月开始每次兔子的数量等于上两个月之和
            sun = old_rubblt + new_rubbit;//因为是第三个月开始的 所以第三个月的开始兔子为2只
//           这里表示的是当前月起算上上个月的赋值给上个月的,当下一次循环开始就会成为上上个月
            old_rubblt = new_rubbit;
            new_rubbit = sun;//将本月的兔子总数赋值 当下一次循环的时候将会变成上个月
            System.out.println("第"+i+"个月的兔子总数为:"+sun);
        }

输出
在这里插入图片描述

递归的小结

  1. 一个递归的方法每次用不同的参数值反复调用自身,
  2. 某个参数值时递归的方法返回,而不再调用自身,这种成为基值情况,
  3. 当递归方法返回时,递归过程通过质检完成各层方法实例的未执行部分,而从最内返回到最外层的原始调用处。
  4. 二分查找可以通过检查查找关键字在有系列的那一半,然后在这一办做相同的事情,这些都可以用递归实现
  5. 汉诺塔的问题半寒了三个塔座和任意数量的盘子,
  6. 汉诺塔难题可以用递归来解决,把出了最低端盘子外的所有盘子形成的字数移到一个中介塔,然后把最低端的盘子移到目标塔,就这样循环直到完成
  7. 归并两个有序的数组意思是创建第三个数组,这个数组按照顺序存储从这个两个有序中取到的所有数据项
  8. 归并排序需要一个大小等于原来数组的工作空间
  9. 对于汉诺塔和归并排序问题,他们的递归的方法包括两次递归调用
  10. 任何可以用递归完成的操作都可以用一个栈来实现
  11. 递归的方法可能效率低,如果是这样的话,有时可以用一个简单循环或者是一个基于栈的方法来代替
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值