一、函数的递归
本次博客主要是通过各种例题给大家讲讲递归算法。
1、什么是递归
程序 调用自身 的编程技巧称为递归 。一个函数在其定义或说明中有直接或间接调用自身的一种方法,它通常 把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题 来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的主要思考方式在于:把大事化小
1.练习1:(画图讲解)
接收一个整型值(无符号),按照顺序打印它的每一位。
例如:
输入:1234 输出:1 2 3 4
思考:
下面是画图详解:
函数的执行顺序是:红色箭头 -> 蓝色箭头
2、由上面递归函数可以看出,递归的两个必要条件:
a.存在限制条件,当满足这个限制条件的时候,递归便不再继续
b.每次递归调用之后越来越接近这个限制条件
下面我们来讲一讲关于栈溢出的问题
编译结果:死循环 栈溢出了
调试结果:栈溢出(Stack overflow)
为什么会导致栈溢出呢?
原因是这个吖子的:
2.练习2:(画图讲解)
编写函数不允许创建临时变量,求字符串的长度。
当然,上面的代码还只是一个影子(题目要求的是编写函数,不允许创建临时变量)
下面,我们用递归来解决一下:
画图讲解(abcdef\0太多了,就abcd\0吧)
二、递归与迭代
总的来说,递归就可以看成是自己调用自己,而迭代的话就可以理解成循环
3、练习3
求n的阶乘
以前写的代码(循环/迭代)
用递归试试看
我们在主函数里面写后续要被调用的某个函数的时候,先假设要用这个函数实现什么功能,直接去用,之后再去真正定义并实现这个函数。
这种思想叫做:TDD - 测试驱动开发 先去想函数怎么用,然后再实现。下面用画图来表示出3的阶乘
的确,有些情况下递归和循环都可以解决,有些情况下却是不可以
4、练习4
求第n个斐波那契数列(不考虑栈溢出)
说明:斐波那契数列用递归的范式算较大的数字是特别浪费时间,甚至会程序崩溃
因此,斐波那契数列不适合用递归去运算
下面用迭代的方式试一下:
虽然这个结果数字太大的话可能是错的(数字太大的话在整型变量是放不下的) ,但是效率比较高,一瞬间就出现结果了
什么时候用递归:
1、当解决一个问题递归和非递归都可以使用,且没有明显问题,那就可以使用递归;
2、当解决一个问题递归写起来很简单,非递归比较复杂,且递归没有明显问题,那就用
递归;
3、如果说用递归解决问题,写起来简单,但是有明显问题,那就不能使用递归,得使用非递归的方式来。