程序调用自身的编程技巧称为递归( recursion)。递归做为一种算法在程序设计语言中普遍应用。一个方法或函数在其定义或说明中有直接或间接调用自身的一种方法,它一般把一个大型复杂的问题层层转化为一个与原问题类似的规模较小的问题来求解,递归策略只须要少许的程序就能够描述出解题过程所须要的屡次重复计算,大大地减小了程序的代码量,让程序更加的简洁。java
例如求和问题:若要求解S100 = 1 + 2 + 3 + 4 + …. + 100的值,经过循环的方式代码以下:算法
int sum = 0; for (int i = 1; i <= 100; i++) { sum = sum + i; }
经过递归方式是如何求解呢?由 1 + 2 + 3 + 4 + …. + 100 能够分解为 ( 1 + 2 + 3 + 4 + …. + 99) + 100,能够看出
S100 = S99 + 100,能够得出 Sn = Sn-1 + n。经过递归的方式代码以下:编程
public int sum(int n) { if (n == 1) { return 1; } else { return sum(n - 1) + n; } }
经过递归代码能够看出,sum() 方法中又调用了其自身,只是将传入的参数发生改变。这种程序调用自身的方式就是递归。函数
什么样的问题才可使用递归的方式求解呢?构成递归须要具有两个条件:
(1)子问题与原始问题属于一样的事情,两者的求解方法是相同的,且子问题比原始问题更易求解。
(2)递归不能无限制地调用自己,必须有个递归出口。递归出口对应的情形相对简单,能够化简为非递归情况处理。设计
斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:
一、一、二、三、五、八、1三、2一、3四、……
在数学上,斐波纳契数列以以下被以递推的方法定义:
F(1)=1,F(2)=1,,F(n) = F(n-1) + F(n-2)(n>=3,n∈N*)。code
问题分析:
斐波那契数列的对于原问题F(n)的求解能够转为对F(n-1)、F(n-2)两个子问题的求解,故符合条件(1)。由F(1)=1,F(2)=1,能够得出斐波那契数列问题是有递归出口的,递归出口对应F(1) = 1,F(2) = 1。求解斐波那契数列的代码以下:递归
public class FibonacciSequence { public static void main(String[] args){ System.out.println(Fribonacci(9)); } public static int Fribonacci(int n){ if(n <= 2) return 1; else return Fribonacci(n-1)+Fribonacci(n-2); } }
阶乘问题的数学表达式为:n! = n * (n-1) * (n-2) * …* 1 (n>0)。经过分析能够得出n! = (n-1)! * n。令F(n) = n!,则F(n) = F(n-1) * n。则阶乘问题符合条件(1)。由0! = 1,能够得出F(0) = 1。则阶乘问题符合条件(2),递归出口为F(0) = 1。利用递归求解阶乘问题代码以下:ci
int factorial(int n) { int sum = 0; if (0 == n) return 1; else sum = n * factorial(n-1); return sum; }
二叉树的遍历代码以下:数学
/* 前序遍历算法 */ void PreOderTraverse(BiTree T) { if(T == NULL) return; printf("%c",T->data); //显示结点数据,能够更改成其余对结点操做 PreOderTraverse(T->lchild); //先遍历左子树 PreOderTraverse(T->rchild); //最后遍历右子树 } /* 中序遍历递归算法 */ void InOderTraverse(BiTree T) { if(T == NULL) return ; InOderTraverse(T->lchild); //中序遍历左子树 printf("%c",T->data); //显示结点数据,能够更改成其余对结点的操做 InOderTraverse(T->rchild); //最后中序遍历右子树 } /* 后序遍历递归算法 */ void PostOderTraverse(T) { if(T==NULL) return; PostOderTraverse(T->lchild); //先遍历左子树 PostsOderTraverse(T->rchild); //再遍历右子树 printf("%c",T->data); //显示结点数能够更改成其余对结点数据 }
经过代码能够看出,二叉树的遍历过程使用递归方式实现既有助于理解,又简化了代码量。io
使用递归求解问题就比如,你手中有一把钥匙想要打开一扇门。当你打开面前这扇门,看到屋里面还有一扇门。你走过去,发现手中的钥匙还能够打开它,你推开门,发现里面还有一扇门,你继续打开它。若干次以后,你打开面前的门后,发现只有一间屋子,没有门了。而后,你开始原路返回,每走回一间屋子,你数一次,走到入口的时候,你能够回答出你到底用这你把钥匙打开了几扇门。 递归算法的应用十分普遍,应用递归算法可使你的代码根据“优雅”。