常用算法(一)——递归(斐波那契数列和汉诺塔算法)

1.递归定义

在一个方法(函数)的内部调用该方法(函数)本身的编程方式。

2.递归实现

(1)错误写法:

  递归最容易引发的一个异常是栈溢出异常

  如果一直递归,没有结束条件,就会无限进行下去,引发栈溢出异常。

package cn.kimtian.normalalgorithm;

/**
 * 递归
 *
 * @author kimtian
 */
public class TestRecursive {
    public static void main(String[] args) {
        print(10);
    }

    public static void print(int i) {
        System.out.println(i);
        //一直向下递归,没有终止
        print(i - 1);
    }
}

异常如下:

(2)正确写法:

  所以递归一定要加终止条件。

package cn.kimtian.normalalgorithm;

/**
 * 递归
 *
 * @author kimtian
 */
public class TestRecursive {
    public static void main(String[] args) {
        print(10);
    }

    public static void print(int i) {
        //当大于0的时候,进行打印,作为终止条件。
        if (i > 0) {
            System.out.println(i);
            print(i - 1);
        }
    }
}

 3.斐波那契数列

费波那契数列由0和1开始,之后的费波那契系数就是由之前的两数相加而得出。首几个费波那契系数是:

0,1,1,2,3,5,8,13,21,34,55,89,144,233……(OEIS中的数列A000045)

斐波那契是以递归的方式来实现的:

package cn.kimtian.normalalgorithm;

/**
 * 斐波那契数列
 *
 * @author kimtian
 */
public class TestFebonacci {
    public static void main(String[] args) {
        //斐波那契数列1,1,2,3,5,8,13,21,34,55,89,144,233……
        System.out.println(febonacci(13));
    }

    public static int febonacci(int i) {
        //前两个值都是1
        if (i <= 2) {
            return 1;
        }
        //第三项开始为前两项的和
        else {
            return febonacci(i - 1) + febonacci(i - 2);
        }
    }

}

4.汉诺塔问题

汉诺塔是根据一个传说形成的数学问题:

有三根杆子A,B,C。A杆上有 N 个 (N>1) 穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至 C 杆:

  1. 每次只能移动一个圆盘;
  2. 大盘不能叠在小盘上面。

提示:可将圆盘临时置于 B 杆,也可将从 A 杆移出的圆盘重新移回 A 杆,但都必须遵循上述两条规则。

package cn.kimtian.normalalgorithm;

/**
 * 汉诺塔问题
 *
 * @author kimtian
 */
public class TestHanoi {
    public static void main(String[] args) {
        hananoi(4, 'A', 'B', 'C');
    }

    /**
     * 汉诺塔移动问题
     *
     * @param n    共有n个盘子
     * @param from 开始的柱子
     * @param in   中间的柱子
     * @param to   目标柱子
     * 无论有多少个盘子,都认为只有两个,上面的所有盘子和最下面的一个盘子
     */
    public static void hananoi(int n, char from, char in, char to) {
        //只有一个盘子
        if (n == 1) {
            System.out.println("第1个盘子从" + from + "移动到" + to);
        }
        //无论有多少个盘子,都认为只有两个,上面的所有盘子和最下面的一个盘子
        else {
            //移动上面所有的盘子到中间位置
            hananoi(n-1, from, to, in);
            //移动最下面的盘子
            System.out.println("第" + n + "个盘子从" + from + "移动到" + to);
            //把上面的所有盘子从中间位置移到目标位置
            hananoi(n-1, in, from, to);
        }

    }
}

猜你喜欢

转载自blog.csdn.net/third_/article/details/86003736
今日推荐