对递归程序一直是一知半解,对于简单的递归程序,我大致能弄懂整个流程,但是复杂点的递归程序(比如说树的各种递归)就一头雾水。今天在看知乎时,看到一个非常不错的建议。大致如下。
写递归函数要处理好递归的3个主要点:
a) 出口条件,即递归通常什么时候结束,这个通常在递归函数的开始就写好;
b) 如何由”情况 n” 变化到”情况 n+1”, 也就是非出口情况,也就是一般情况——”正在”递归中的情况;
c) 初始条件,也就是这个递归调用以什么样的初始条件开始。
有几句不错的话:
1、每次传递状态信息作为参数。合理的设计参数是重点。
2、函数用栈存储中间过程和返回值,递归函数调用时压栈,最终会返回栈底的元素
今天在stackoverflow上发现了一个递归模板感觉不错。是Eric Lippert写的,这位大神是前微软C#编译器团队的首席开发师,膜拜。。。毕竟我本科的时候都是用C#写东西,研究生期间入了机器学习的坑,才不得已舍弃了C#。不得不说visual studio真好用,秒杀市场上所有IDE(个人见解,勿喷)。好吧,好像和我想讲的递归扯远了。。。
下面我们来看下这个模板。
{
if (<problem can be solved easily>)
return <easy solution>;
// The problem cannot be solved easily.
Problem smaller1 = <reduce problem to smaller problem>
Result result1 = M(smaller1);
Problem smaller2 = <reduce problem to smaller problem>
Result result2 = M(smaller2);
...
Result finalResult = <combine all results of smaller problem to solve large problem>
return finalResult;
}
他在后面还用了一个求二叉树深度的例子。
int Depth(Tree tree)
{
// Start with the trivial case. Is the tree empty?
if (tree.IsEmpty) return 0;
// The tree is not empty.
// Reduce the problem to two smaller problems and solve them:
int depthLeft = Depth(tree.Left);
int depthRight = Depth(tree.Right);
// Now combine the two solutions to solve the larger problem.
return Math.Max(depthLeft, depthRight) + 1;
}
模板简洁明了!
以后看到对递归比较好的阐述还会再加上。