编程语言中,一个函数在它的函数体调用它自身的过程叫做递归调用。这种函数称为递归函数。
在数学上,关于递归函数的定义如下:对于某一函数f(x),其定义域是集合A,那么若对于A集合中的某一个值X0,其函数值f(x0)由f(f(x0))决定,那么就称f(x)为递归函数。
一种计算过程,如果其中每一步都要用到前一步或前几步的结果,称为递归的。用递归过程定义的函数,称为递归函数,例如连加、连乘及阶乘等。凡是递归的函数,都是可计算的,即能行的。
古典递归函数,是一种定义在自然数集合上的函数,它的未知值往往要通过有限次运算回归到已知值来求出,故称为“递归”。它是古典递归函数论的研究对象 。
在数理逻辑和计算机科学中,递归函数或μ-递归函数是一类从自然数到自然数的函数,它是在某种直觉意义上是"可计算的" 。
一个直接的例子
//代码1
Void fus()
{
//...
if(...)
fus();
else
//...
}
条件
一个含直接或间接调用本函数语句的函数被称之为递归函数,在上面的例子中能够看出,它必须满足以下两个条件:
1) 在每一次调用自己时,必须是(在某种意义上)更接近于解;
2) 必须有一个终止处理或计算的准则。
例如:
用递归计算f(n)=n!
//当0<=n<2 fus(n)=1
//当n>1 fus(n)=fus(n-1)*n
#include<stdiio.h>
int fus(int n)
{
int x;
if(0<=n<2)
x=1;
else
z=fus(n-1)*n;
return(z);
}
int main()
{
int n, y;
scanf("%d",&n);
if(n>0)
{
y=fus(n);
printf("%d",y);
}
else
printf("error");
}
计算
函数的概念是一个很一般的概念。在定义函数时,不一定要具体给出通过自变量求函数值的方法。因此,可将函数分成两类,一类是所谓能行可计算函数,另一类是非能行可计算的函数。这前一种函数无论在理论上或在实际上都是非常重要的,因此人们便试图给它们以精确的数学刻画。递归函数便是许多这种刻画中的一种。
我们以下考虑的函数都是从自然数到自然数的函数。
我们先定义几个初等函数
(1)零函数 Z(x)=0;
(2)后继函数 S(x)=x+1;
(3)广义幺函数 U1n(x1,…xn)=xi;
显然,上面这些函数都是能行可计算的。
再介绍几个将函数变换为函数的算子。
(1)复合算子 设f是n元函数,g1…gn是m元函数,复合算子将f,g1…gn变换成为如下的m元函数h:
h(x1…xm)=f1g1(x1,…xm),…gn(x1,…xm))
(2)递归算子 设f是n元函数 (≥0),g是n+2元函数,递归算子将f,g变换成满足下列条件的h+1元函数h:
h(x1,…,xn,0)=f(x1,…xn)
h(x1,…xn,y+1)=g(x1,…xn,y,h(x1,…xn))
(3)μ一算子,设f是n+1元函数,如果存在y,使f(x1,…xn,y)=0,我们以μyf(x1…xny)表示这样的y中的最小者,如果使f(x1…xny)=0的y不存在,我们说μyf(x1,…xny)无定义。μ-算子将n+1元函数f变换成下面的几元函数h
h(x1,…xn)=μyf(x1…xny)
注意,μ算子可以将一个全函数变换成一个部分函数(即在自然数的某个子集上有定义的函数)。
可以看出,上述所有算子都是将能行可计算函数变换为能行可计算函数。
所谓递归函数类便是包含零函数、广义幺函数,并在复合算子、递归算子,μ-算子下封闲的最小函数类。
容易相信,任何递归函数都是能行可计算的。反过来,是否存在直观上能行可计算的,但不是递归的函数呢?人们直到现在还没有发现这样的函数。相反,人们证明了,现已遇到的直观上能行可计算的函数都是递归函数。进一步,人们还证明了,递归函数类与其他的一些刻画能行可计算函数的方法产生的函数类是完全一致的,这些事实促使车尔赤(Church)提出了他的著名的论点:
递归函数类与直观能行可计算函数类是重合的。
这个论点已被大多数递归论学者所接受。
函数的递归调用
1~递归函数的调用与递归函数
一个函数在它的函数体调用它自身的过程叫做递归调用。这种函数称为递归函数。
递归分为直接递归与间接递归两种,直接递归简单地说就是函数自己调用自己,如A()调用A()为直接递归。间接递归是指函数在嵌套调用过程中出现了一种循环调用的现象,也就是出现了函数间接调用自己的情况。如A()调用B(),B()调用A(),等称为间接递归。两种递归的实质是一样的,均出现了函数调用自己的现象
例如有函数
int fus(int a)
{
int b;
c=fus(b);
return c;
}
这是一个递归函数。但是运行该函数将无休止地调用其自身,最后造成系统错误。为了防止递归调用无终止地进行,必须在函数内有终止递归调用的语句。