Java数据结构中有一章来讲递归算法~作为补充。
算法存在自调用的情况一般有两种(1)问题的定义是递推的,比如阶乘。(2)问题的解法存在自调用,比如折半查找。递归算法用把问题分解为形式更加简单的子问题的方法来求解问题,它既是一种有效的分析问题的方法,也是一种有效的算法设计方法。
适宜用递归算法求解的问题的充分必要条件是(1)问题具有某种可借用的类同自身的子问题描述的性质。(2)某一有限步的子问题(本原问题)有直接的解存在。
设计递归算法的方法(1)把对原问题的求解表示成对子问题求解的形式。(2)设计递归出口。
以汉诺塔举例(圆盘从A移至C借助B):
package Recursion;
/**
* @author sun
* 创建时间:2017年4月18日上午9:43:30
*/
//n个盘子和n-1个盘子的递归
public class Hanoi {
public static void towers(int n,char fromPeg,char toPeg,char auxPeg){
//把n个盘子从fromPeg借助auxPeg移至toPeg
if(n==1){//递归出口
System.out.println("move disk 1 from peg "+fromPeg+" to peg "+toPeg);
return;
}
//把n-1个盘子从fromPeg借助toPeg移至auxPeg
towers(n-1,fromPeg,auxPeg,toPeg);
//把盘子n由fromPeg直接移至toPeg
System.out.println("move disk "+n+" from peg "+fromPeg+" to peg "+toPeg);
//把n-1个盘子从auxPeg借助fromPeg移至toPeg
towers(n-1,auxPeg,toPeg,fromPeg);
}
public static void main(String[] args) {
towers(4,'A','C','B');
//把4个盘子从A移到C,借助B。
}
}
/*
move disk 1 from peg A to peg B
move disk 2 from peg A to peg C
move disk 1 from peg B to peg C
move disk 3 from peg A to peg B
move disk 1 from peg C to peg A
move disk 2 from peg C to peg B
move disk 1 from peg A to peg B
move disk 4 from peg A to peg C
move disk 1 from peg B to peg C
move disk 2 from peg B to peg A
move disk 1 from peg C to peg A
move disk 3 from peg B to peg C
move disk 1 from peg A to peg B
move disk 2 from peg A to peg C
move disk 1 from peg B to peg C
*/
外部函数调用递归函数:
递归函数的执行过程具有三个特点:(1)函数名相同;(2)不断的自调用;(3)最后被调用的函数要最先被返回(符合堆栈后进先出的特性)。所以,系统用堆栈来保存递归函数调用时的信息,该堆栈也称为运行时栈,每一层递归调用所需保存的信息构成运行时栈的一个工作记录,栈顶的工作记录也称活动记录。效率分析结果:一般情况下,若循环方式的算法和递归方式的算法均能求解某问题,通常循环方式算法的时间复杂度要比递归方式算法的时间复杂度低很多很多,如斐波那契数列递归:O(2^n),循环O(n)。
递归到非递归的转换:
一般来说,有两种情况可转换(1)有些问题(如阶乘),即存在递归结构算法,也存在循环结构算法;(2)存在借助堆栈的循环结构算法。