写在前面:
对于强大的递归。要想做到灵活运用,是需要花时间进行练习并总结。往往递归学习的入门也是难度也比较大,常常会处于看得明,却写不出的"尴尬"情况。
本人也是一名编程菜鸟,也常处于尴尬中。正因递归的学习需要一个过程,所以萌生一个想法,对于每一次的递归学习都写篇博文总结,与大家分享,共同进步!
在此推荐一本学习递归较好的的入门书:《程序设计抽象思想:C语言描述》 。本文章也引用了书中的对递归要点的理解和描述。
*文章练习会不定期进行更新
递归的简单介绍和要点梳理
递归的定义:
将一个大的问题分解成比较小的、有着相同形式的问题。
递归是一种强有力的思想。在计算机科学的学习中,一个重要的必须学习的概念是递归。递归是一种编程策略,它把一个大的问题分解成具有相同形式的简单问题。
递归示例:(可以按照以下顺序逐步练习递归)
1.阶乘函数
2.斐波那契函数
3.回文字符串
4.字符串翻转
5.折半查找
6.汉诺塔
7.poj放苹果
使用递归的必需条件
- 可以通过递归调用来缩小问题规模,且新问题与原问题有着相同的形式
- 存在一种简单情境,可以使递归在简单情境下退出
一般对递归思想的介绍,都是说将大问题分解为一个个小问题。本人觉得,带着 “如何将问题规模缩少”的思想 比 “将大问题分解为一个个小问题” 的思想要更好地编写递归程序。
递归跳跃的信任
当尝试理解递归程序时,必须能够抛开底层的细节,将注意力集中在单个计算层次上。在这个层次上,只要一个递归调用的参数在某些方面能比前一个参数更简单,那么就可以认为任何递归调用都能够自动地得到正确的答案。这种心理策略——假设任何更简单的递归都能正确地实现——叫做对递归跳跃的信任。在实际应用中,学习应用这个策略是使用递归的基础。
以递归的方式思考
保持整体观:递归思维要求整体考虑。在递归领域中,只考虑局部是理解的敌人,将会妨碍对递归的理解。为了保持这种整体观,必须习惯于采用对递归跳跃的信任。无论是在写递归程序或是理解递归程序,都必须达到忽视单个递归调用细节的地步。只要选择了正确的分解,确认了相应的简单情景,并且正确地实现了策略,那么这些递归调用能够自己运行,不必过多考虑。
避免常见的错误
- 检验递归实现是不是以检查简单情景开始。在几乎所有情况中,递归函数都开始于关键字 if 。如果你的函数不是这样,那么应该仔细检查程序并确信知道自己在做什么
- 正确地解决了简单情景了吗?在递归程序中很多bug都是起源于简单情景的不正确解决。如果简单情景是错误的,那么对更复杂问题的递归解决将会继承相同的错误
- 递归分解使问题更加简单了吗?递归的作用在于,随着问题解决的进行,它将变得越来越就简单。即每一次递归调用中,参数值将会越来越小
- 简化的过程是不是逐渐地达到了简单情景,或者是不是遗漏了一些可能性?常见的一个错误就是没有将全部情况的简单情景测试都包括其中,这些情况可能作为递归分解的结果而产生出来。简单说:你需要正确地将所有的简单情景分析出来
- 函数中的递归调用是不是表示了在形式上和初始问题真的完全相同的子问题?当使用递归分解问题时,关键在于子问题形式的同一性。如果递归调用改变了问题的本性,或者违反了一个初始化的假设,那么全部过程就被破环
- 当使用对递归跳跃的信任时,递归子问题的解决方案是否对初始问题提供了一个完整的解决方案?将一个问题分解为递归子问题仅仅是递归过程的一部分,一旦子问题得到了解决,那么也必须能够将他们重新组装从而得到全部的答案