zoukankan      html  css  js  c++  java
  • 递归算法

    递归算法的描述:

          递归算法是一种直接活着间接调用自身的算法,是把问题转化为规模缩小的同类问题的子问题。与斐波那契数列异曲同工。

          在历史长河之中它解决了什么:

          (1) 斐波那契数列: 斐波纳契数列,又称黄金分割数列,指的是这样一个数列:1123581321、……

          (2) 阶乘 :  n! = n * (n-1) * (n-2) * ...* 1(n>0)

          (3) 河内塔问题 : 

               

            (4) 生兔子问题:    

                 第一个月小兔子没有繁殖能力,所以还是一对;

                 两个月后,生下一对小兔子,总数共有两对;

           三个月以后,老兔子又生下一对,因为小兔子还没有繁殖能力,总数共是三对;

          …… 

               

    递归算法解决问题的特点:

            (1) 递归就是在程序执行的过程中或者函数里调用自身.

            (2) 在使用递归策略时,必须有一个明确的递归结束条件,也就是递归的出口。如果没有出口会怎么样,就会出现死循环,好比我们从小听到的     一个故事一样:

                 从前有座山,山里有个庙,庙里有个老和尚正在讲故事:从前有座山,山里有个庙,庙里有个老和尚正在讲故事:

            从前有座山,山里有个庙,庙里有个老和尚正在讲故事...

            (3) 递归算法解决问题简洁明了,但解决问题的运行效率较低。

                 当看到这个特点的时候不妨想想为什么说它效率低?我能想到的是这样子的,递归算法的自我调用都会走一遍这个方法,那么这个方法里面会干什么,怎么干,如果说在                调用这个函数之前需要准备许多pre的工作,for example:准备变量(需要消耗空间咯),各种判断(一次调用可以不在乎,N次呢),每次调用这个method都会走一              遍这样的流程,自然会开销大一些,这也就显示出来了第(4)点咯。

            (4) 在递归调用的过程中系统为每一层的返回点,局部变量等开辟了栈来存储,递归次数过多容易造成栈溢出等。

                  函数在被调用还没有结束时再次调用该函数,当前的状态会被保存到栈里面去,依此类推,在最后一个函数执行完之后,倒数第二个函数才开始出栈,

            递归算法的分类:

                 分两种:直接递归和间接递归

                 直接递归:method A call itself

                 间接递归:method A call method B, mehod B call method C, metod C call method A

    实现:

    JAVA中的实现

    public class Test {
    
        private static int number;
    
        public static void main(String[] args) {
            int result = recursion(5);
            System.out.println(result);
        }
    
        public static int recursion(int i) {
    
            number++;
            System.out.println("In--" + number + "--i = " + i);
    
            if (i == 0) {
                return 0;
            } else if (i == 1) {
                return 1;
            } else {
                return recursion(i - 1) + recursion(i - 2);
            }
        }
    
    }

    结果:

    In--1--i = 5
    In--2--i = 4
    In--3--i = 3
    In--4--i = 2
    In--5--i = 1
    In--6--i = 0
    In--7--i = 1
    In--8--i = 2
    In--9--i = 1
    In--10--i = 0
    In--11--i = 3
    In--12--i = 2
    In--13--i = 1
    In--14--i = 0
    In--15--i = 1

    看到如下结果,是否想一想程序是怎么走的呢?请看如下图:

    河内塔问题

        public static void hanoi(int n, int p1, int p2, int p3) {
            if (1 == n) {
                System.out.println("盘子" + n + "从" + p1 + "移到" + p3);
            } else {
                hanoi(n-1, p1, p3, p2);
                System.out.println("盘子" + n + "从" + p1 + "移到" + p3);
                hanoi(n-1, p2, p1, p3);
            }
        }

    结果:

    盘子1从1移到3
    盘子2从1移到2
    盘子1从3移到2
    盘子3从1移到3
    盘子1从2移到1
    盘子2从2移到3
    盘子1从1移到3

    如何优化这类问题,请看我的另一篇博客 : 

    对费波纳契数列的几种算法实现对比分析

    引用:

    1. 汉诺塔

    2. https://www.zhihu.com

    3. http://www.cnblogs.com/joinclear/archive/2013/02/06/2908247.html

  • 相关阅读:
    内存泄漏检测工具VLD在VS2010中的使用举例
    boost::threadpool 调用类成员变量并传入参数 的方法
    boost之ThreadPool
    DllMain 用法
    分布式锁的几种实现方式
    利用cbmakegen导出Code::blocks的Makefile
    搜集C++实现的线程池
    微软开源rDSN分布式系统开发框架
    腾讯互娱开源分布式开发框架Pebble
    SpringBoot指定额外需要扫描的包
  • 原文地址:https://www.cnblogs.com/chenyongblog/p/5116563.html
Copyright © 2011-2022 走看看