C++函数有一个有趣的特点,即自己可以调用自己(当然main函数除外),此所谓递归。其工作目的是把算法写的比使用非递归函数时更清晰更简洁,而且某些问题,特别是与人工智能有关的问题,更适宜用递归方法。递归的另一个优点是,递归函数不会受到怀疑,较非递归函数而言,某些人更相信递归函数。编写递归函数时,必须在函数的某些地方使用if语句,强迫函数在未执行递归调用前返回。如果不这样做,在调用函数后,它永远不会返回。一个典型的递归函数模型:
void recurs(formalparamelist)
{
statements1;
if(test)
recurs(realparamelist);
statements2;
}
该模型不难理解,recurs函数自身调用了recurs本身,只要test条件满足,就会一直循环调用自身。当test条件不成立,函数将执行statements2,并将程序的控制权返回给调用当前层的recurs,该recurs继续执行statements2,以此类推直到回到最原始(即最高)层,至此递归函数执行完毕。这里援引C++ primer plus书中的一个实例:
#include <iostream>
void countdown(int n)
int main()
{
countdown(4)<span style="font-family:Microsoft YaHei;">;
return 0;
}
void countdown(int n)
{
using namespace std;
cout<< "counting down..."<< n << end1;
if(n>0)
countdown(n-1);
cout<< n << ":Kaboom!\n";
}
很简单但是很方便理解的代码,但是肯定会有人对输出结果的顺序迷惑不解:为什么不是一条counting down紧接着一条Kaboom而是先输出完所有的counting down才输出Kaboom呢?下面我们先看打印输出:
解释如下:为了分析简便,我们假设这里的n=1,函数首先输出counting down...1,紧接着调用countdown(1-1)=countdown(0);那么这个countdown(0)的执行结果是什么呢?没错,执行结果就是
counting down...0
0:Kaboom!
countdown(0)执行完毕之后呢?显然会继续执行cout<<1<<":Kaboom!"; 即countdown(1)中的statements2语句。所以执行结果:
counting down...1
counting down...0
0:Kaboom!
1:Kaboom!
再看一个比较有趣的例子:
#include "stdafx.h"
int f(int m, int n);
int main() {
int result = 0;
result = f(2, 3);
printf("%d", result);
return 0;
}
int f(int m, int n)
{
if (m == 0 || n == 0) return 1;
printf("%d\t",m);
printf("%d\n", n);
return f(m - 1, n) + f(m, n - 1);
}
这个函数的输出结果如下:
输出是不是看起来很难解释?其实只要能理清递归的流程,画出二叉树来,问题就轻松解决了。
图中红色的节点表示递归的尽头,黑色节点表示继续调用递归函数,每一个红色节点的值都为1,求和即为10,也就是result的值;紫色虚线指示了递归的方向,对应着m和n值的输出。如此一来,输出结果就和图中所描述的一模一样了。