递归与尾递归
2016-01-20 19:32
246 查看
摘要: 递归简单来说就是一个函数直接或间接的调用自身,当未达到递归的边界条件时函数会继续递归调用函数自身,若达到边界条件则递归返回。
普通递归执行时,每一层函数的返回都要依赖于下一层函数的返回值,系统为会开辟栈来存储每一层函数的返回点、局部变量,因此递归次数越多,需要保存的中间函数的堆栈就越多,消耗的系统资源就越多,甚至会造成栈溢出。
尾递归,上层函数会把当前的计算结果作为参数传给下层函数,函数调用总是出现在调用函数的尾部,所以没有必要保存每一次函数调用时的局部变量,只用保留最后一个函数的堆栈即可,因此性能比普通递归要好。
递归简单来说就是一个函数直接或间接的调用自身,当未达到递归的边界条件时函数会继续递归调用函数自身,若达到边界条件则递归返回。
普通递归执行时,每一层函数的返回都要依赖于下一层函数的返回值,系统为会开辟栈来存储每一层函数的返回点、局部变量,因此递归次数越多,需要保存的中间函数的堆栈就越多,消耗的系统资源就越多,甚至会造成栈溢出。
尾递归,上层函数会把当前的计算结果作为参数传给下层函数,函数调用总是出现在调用函数的尾部,所以没有必要保存每一次函数调用时的局部变量,只用保留最后一个函数的堆栈即可,因此性能比普通递归要好。
以下是用java实现递归与尾递归的一个例子:
普通递归执行时,每一层函数的返回都要依赖于下一层函数的返回值,系统为会开辟栈来存储每一层函数的返回点、局部变量,因此递归次数越多,需要保存的中间函数的堆栈就越多,消耗的系统资源就越多,甚至会造成栈溢出。
尾递归,上层函数会把当前的计算结果作为参数传给下层函数,函数调用总是出现在调用函数的尾部,所以没有必要保存每一次函数调用时的局部变量,只用保留最后一个函数的堆栈即可,因此性能比普通递归要好。
递归简单来说就是一个函数直接或间接的调用自身,当未达到递归的边界条件时函数会继续递归调用函数自身,若达到边界条件则递归返回。
普通递归执行时,每一层函数的返回都要依赖于下一层函数的返回值,系统为会开辟栈来存储每一层函数的返回点、局部变量,因此递归次数越多,需要保存的中间函数的堆栈就越多,消耗的系统资源就越多,甚至会造成栈溢出。
尾递归,上层函数会把当前的计算结果作为参数传给下层函数,函数调用总是出现在调用函数的尾部,所以没有必要保存每一次函数调用时的局部变量,只用保留最后一个函数的堆栈即可,因此性能比普通递归要好。
以下是用java实现递归与尾递归的一个例子:
public class TestRecursion { // 斐波那契数列,普通递归实现 public static int fibonacciRecursive(int n) { if (n < 2) { return n; } return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2); } // 斐波那契数列,尾递归实现 public static int fibonacciTailRecursive(int n, int i1, int i2) { if (n == 0) { return i1; } return fibonacciTailRecursive(n - 1, i2, i1 + i2); } // 求n的阶乘,普通递归实现 public static int factorialRecursive(int n) { if (n < 2) { return n; } return n * factorialRecursive(n - 1); } // 求n的阶乘,尾递归实现 public static int factorialTailRecursive(int n, int i) { if (n < 0) { return 0; } else if (n == 0) { return 1; } else if (n == 1) { return i; } return factorialTailRecursive(n - 1, i * n); } public static void main(String[] args) { // 斐波那契数列 System.out.println(fibonacciRecursive(9)); System.out.println(fibonacciTailRecursive(9, 0, 1)); // 求n的阶乘 System.out.println(factorialRecursive(10)); System.out.println(factorialTailRecursive(10, 1)); } }
相关文章推荐
- MyBatis批量插入数据
- C++:重载函数2(计算面积)
- U8SDK——Cocos2dx游戏快速渠道SDK接入
- 使用autoCompleteTextView以及MultiAutoCompleteTextView实现自动匹配输入内容
- linux grep命令详解
- Quartz2.2.1开发问题
- Quartz2.2.1开发问题
- 修改apache服务器根目录
- 关于NSCache的使用
- Netty使用Marshalling传输信息
- springMVC 接收数组参数,mybatis 接收数组参数,mybatis批量插入/批量删除案例
- Synchronized
- 深度学习框架Caffe的编译安装
- 《魔兽世界》的魅力究竟在哪儿?
- mysql + SpringMVC + MyBatis中批量插入实例以及@Param注解的用法
- LeetCode Edit Distance
- APUE读书笔记
- Xenomai 安装准备工作
- linux read命令详解
- Python中使用urllib2模块编写爬虫的简单上手示例