递归简介
Big Recursive Idea
《像程序员一样思考》 第六章
1. 递归基础知识
当一个函数在任意时候调用自身就发生了递归调用,因此递归语法就是函数调用的语法。递归函数包括 基本情况 和 递归调用 两个部分。递归要求我们对问题进行细分,把原问题的一个消减版本传递给递归调用,然后通过基本情况结束递归。
\[递归函数 \begin {cases}
基本情况, \space 不需要递归就能返回值 \\
递归调用
\end{cases}
\]
当你考虑使用递归来解决问题时, 首先思考 基本情况 是很有意义的。
递归包含直接递归(自己调用自己)和间接递归,直接递归又包含头递归和尾递归。在头递归中, 递归发生在函数处理其他代码之前,尾递归与之相反,头递归好处在于允许递归调用传递尽量少的数据(形参)。 头递归利用返回值传递信息(由于返回值很麻烦, 通常我们使用全局变量来达到目的), 尾递归利用形参传递信息
2. 大递归思路
何谓大递归思路?
将递归调用看成是对另一个函数的调用,而不需要考虑函数的内部细节。
对于递归函数来说,函数的形参的选择极其重要,可以说正是形参的变化将原问题变成了更小规模的子问题。
在递归函数中,只要有可能,应该尽量避免使用全局变量。
递归常用于链表(头结点和尾部),树(根节点,左子树,右子树)和图这样动态数据结构。
3. 包装器函数
包装器非常适合于在类的内部编写递归函数, 它们可以用于在函数所需要的参数列表和调用者所传递的参数的列表不匹配的任意场合使用。
// 计算树的叶子树,客户端代码不需要传递任何参数,而且树的根节点为私有属性
private int privateCountLeaves(BinaryNode root)
public int countLeaves()