浅谈什么是递归算法
1 引言
程序调用自身的编程技巧称为递归( recursion)。递归作为一种算法在程序设计语言中广泛应用。一个方法或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。 例如求和问题:若要求解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() 方法中又调用了其自身,只是将传入的参数发生改变。这种程序调用自身的方式就是递归。
2 应用场景
什么样的问题才可以使用递归的方式求解呢?构成递归需要具备两个条件: (1)子问题与原始问题为同样的事情,二者的求解方法是相同的,且子问题比原始问题更易求解。 (2)递归不能无限制地调用本身,必须有个递归出口。递归出口对应的情形相对简单,可以化简为非递归状况处理。
3 实例
3.1 斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列: 1、1、2、3、5、8、13、21、34、…… 在数学上,斐波纳契数列以如下被以递推的方法定义: F(1)=1,F(2)=1,,F(n) = F(n-1) + F(n-2)(n>=3,n∈N*)。
问题分析: 斐波那契数列的对于原问题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);
}
}
3.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。利用递归求解阶乘问题代码如下:
int factorial(int n)
{
int sum = 0;
if (0 == n)
return 1;
else
sum = n * factorial(n-1);
return sum;
}
3.3 树的遍历
对于树遍历问题在之前树的专题中已经详细介绍,这里不再赘述。二叉树的遍历代码如下:
/*前序遍历算法*/
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); //显示结点数可以更改为其他对结点数据
}
通过代码可以看出,二叉树的遍历过程使用递归方式实现既有助于理解,又简化了代码量。
4 结语
使用递归求解问题就好比,你手中有一把钥匙想要打开一扇门。当你打开面前这扇门,看到屋里面还有一扇门。你走过去,发现手中的钥匙还可以打开它,你推开门,发现里面还有一扇门,你继续打开它。若干次之后,你打开面前的门后,发现只有一间屋子,没有门了。然后,你开始原路返回,每走回一间屋子,你数一次,走到入口的时候,你可以回答出你到底用这你把钥匙打开了几扇门。 递归算法的应用十分广泛,应用递归算法可以使你的代码根据“优雅”。
- SQL Server 深入解析索引存储(下)
- 2751: [HAOI2012]容易题(easy)
- codevs3002 石子归并 3
- 算法模板——计算几何2(二维凸包——Andrew算法)
- 算法模板——splay区间反转 2
- 算法模板——Dinic网络最大流 2
- 1935: [Shoi2007]Tree 园丁的烦恼
- 1339 / 1163: [Baltic2008]Mafia
- 4010: [HNOI2015]菜肴制作
- 4052: [Cerc2013]Magical GCD
- ElasticSearch搜索引擎在SpringBoot中的实践
- 2292: 【POJ Challenge 】永远挑战
- 四边形不等式优化DP
- 4063: [Cerc2012]Darts
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Java自动化测试(selenium 22)
- linux 实现双网卡绑定单个IP——team篇
- Eclipse华丽转身之控件表格工厂
- 面试常考知识点总结——面试必看
- linux 实现双网卡绑定单个IP——bond篇
- Hacking with iOS: SwiftUI Edition - 愿望清单项目(一)
- 重拾Java Web应用的基础体系结构
- 使用SAP C4C自定义BO实现自定义的Number Range
- 限流算法简介及Guava RateLimiter令牌桶限流介绍
- K8S的名称空间创建&&版本的升级、回滚操作
- SAP Cloud for Customer CLR(Code List Restriction)的一种高级用法
- SAP WebClient UI One Hit Navigation的实现方法
- 【打包构建】Mac下使用expect实现执行sudo命令时自动输入密码
- ASP.NET Core 奇淫技巧之SPA部署
- SAP Cloud for Customer Rule Editor的使用方法和底层工作原理