递归函数的例子(递归函数怎么用)
大家好,递归函数的例子相信很多的网友都不是很明白,包括递归函数怎么用也是一样,不过没有关系,接下来就来为大家分享关于递归函数的例子和递归函数怎么用的一些知识点,大家可以关注收藏,免得下次来找不到哦,下面我们开始吧!
c语言中,什么是函数的递归,能举个例子么
所谓递归,说的简单点,就是函数自己调用自己,然后在某个特定条件下。结束这种自我调用。
如果不给予这个结束条件,就成了无限死循环了。这样这个递归也就毫无意义了。
如下面问题
1 1 2 3 5 8 13 21........n
分析可以看出, i表示第几个数, n表示该数的值
当i= 1时, n= 1;
当i= 2时, n= 1;
当i= 3时 n= i1+ i2;
当i= 4时 n= i2+ i3
所以可以写个函数
int fun(int n)//这里的n代表第几个数
{
if(1== n|| 2== n)//第一个数
{
return 1;
}
else
{
return fun(n- 1)+ fun(n- 2);//这里就是自己调用自己,形成循环自我调用。
}
}
注:以上代码只是用来演示递归,不包含错误校验。
在实际生产过程中。该代码不够健壮。
如此,就完成了递归。你就可以求得第n个数了。
何时考虑使用递归。
当你分析一个问题的时候,发现这个问题,是一个自我循环时,而且这个自我循环到一个给定值,就可以终止的时候,你就快要考虑递归了。
c语言函数的递归调用
这段程序的意思是对传来的参数n,如果n<1,程序会崩溃;如果n>1则没大1,返回就多2,最后必然会执行c=10。比如n=5,则返回的是18((5-1)x2+10=18)
比如说做了5次递归,即n=5;执行的操作如下:
第1次调用(n=5),定义了一个intc;
第2次调用(n=4),定义了一个intc;
第3次调用(n=3),定义了一个intc;
第4次调用(n=2),定义了一个intc;
低5次调用(n=1),定义了一个intc;
n=1时,满足了条件n==1,故此时c=10;
第5次返回,此时第5次定义的c=age(intn)=10;前4次定义的intc没有值,下同
第4次返回,此时第4次定义的c=age(intn)+2=10+2=12
第3次返回,此时第3次定义的c=age(intn)+2=12+2=14
第2次返回,此时第2次定义的c=age(intn)+2=14+2=16
第一次返回,此时第一次定义的c=age(intn)+2=16+2=18。此时按下面的程序b接收了返回值
我觉得你应该注意的是age(intn)本身就代表一个int值,就算没有参数接收也可以参与到运算当中,就像这个例子一样。
程序:
#include<stdio.h>
intage(intn)
{intc;
if(n==1)
c=10;
else
c=age(n-1)+2;
returnc;
}
voidmain()
{
inta=0,b=0;
scanf("%d",&a);
b=age(a);
printf("resultis%d
",b);
}
尾递归的实例
为了理解尾递归是如何工作的,让我们再次以递归的形式计算阶乘。首先,这可以很容易让我们理解为什么之前所定义的递归不是尾递归。回忆之前对计算n!的定义:在每个活跃期计算n倍的(n-1)!的值,让n=n-1并持续这个过程直到n=1为止。这种定义不是尾递归的,因为每个活跃期的返回值都依赖于用n乘以下一个活跃期的返回值,因此每次调用产生的栈帧将不得不保存在栈上直到下一个子调用的返回值确定。现在让我们考虑以尾递归的形式来定义计算n!的过程。
这种定义还需要接受第二个参数a,除此之外并没有太大区别。a(初始化为1)维护递归层次的深度。这就让我们避免了每次还需要将返回值再乘以n。然而,在每次递归调用中,令a=na并且n=n-1。继续递归调用,直到n=1,这满足结束条件,此时直接返回a即可。
代码实例3-2给出了一个C函数facttail,它接受一个整数n并以尾递归的形式计算n的阶乘。这个函数还接受一个参数a,a的初始值为1。facttail使用a来维护递归层次的深度,除此之外它和fact很相似。读者可以注意一下函数的具体实现和尾递归定义的相似之处。
示例3-2:以尾递归的形式计算阶乘的一个函数实现/*facttail.c*/#includefacttail.h/*facttail*/intfacttail(intn,inta){/*Computeafactorialinatail-recursivemanner.*/if(n<0)return0;elseif(n==0)return1;elseif(n==1)returna;elsereturnfacttail(n-1,n*a);}示例3-2中的函数是尾递归的,因为对facttail的单次递归调用是函数返回前最后执行的一条语句。在facttail中碰巧最后一条语句也是对facttail的调用,但这并不是必需的。换句话说,在递归调用之后还可以有其他的语句执行,只是它们只能在递归调用没有执行时才可以执行。尾递归是极其重要的,不用尾递归,函数的堆栈耗用难以估量,需要保存很多中间函数的堆栈。比如f(n, sum)= f(n-1)+ value(n)+ sum;会保存n个函数调用堆栈,而使用尾递归f(n, sum)= f(n-1, sum+value(n));这样则只保留后一个函数堆栈即可,之前的可优化删去。
也许在C语言中有很多的特例,但编程语言不只有C语言,在函数式语言Erlang中(亦是栈语言),如果想要保持语言的高并发特性,就必须用尾递归来替代传统的递归。
原文的说法是错误的:原文如下:
一种算法,用于计算机编程技术.
尾递归是针对传统的递归算法而言的,传统的递归算法在很多时候被视为洪水猛兽.它的名声狼籍,好像永远和低效联系在一起.
尾递归就是从最后开始计算,每递归一次就算出相应的结果,也就是说,函数调用出现在调用者函数的尾部,因为是尾部,所以根本没有必要去保存任何局部变量.直接让被调用的函数返回时越过调用者,返回到调用者的调用者去.
以下是具体实例:
线性递归: longRescuvie(longn){return(n==1)?1:n*Rescuvie(n-1);}尾递归: longTailRescuvie(longn,longa){return(n==1)?a:TailRescuvie(n-1,a*n);}longTailRescuvie(longn){//封装用的return(n==0)?1:TailRescuvie(n,1);}当n= 5时
对于线性递归,他的递归过程如下:
Rescuvie(5)
{5* Rescuvie(4)}
{5*{4* Rescuvie(3)}}
{5*{4*{3* Rescuvie(2)}}}
{5*{4*{3*{2* Rescuvie(1)}}}}
{5*{4*{3*{2* 1}}}}
{5*{4*{3* 2}}}
{5*{4* 6}}
{5* 24}
120
对于尾递归,他的递归过程如下:
TailRescuvie(5)
TailRescuvie(5, 1)
TailRescuvie(4, 5)
TailRescuvie(3, 20)
TailRescuvie(2, 60)
TailRescuvie(1, 120)
120
很容易看出,普通的线性递归比尾递归更加消耗资源,在实现上说,每次重复的过程
调用都使得调用链条不断加长.系统不得不使用栈进行数据保存和恢复.而尾递归就
不存在这样的问题,因为他的状态完全由n和a保存.
具体事例2快速排序算法实施尾递归优化 voidquickSort(SqList*list,intlow,inthigh){intpivot;while(low<high){pivot=Partition(list,low,high);quickSort(list,low,pivot-1);//quickSort(list,low,pivot-1);原递归调用//quickSort(list,pivot+1,high);low=pivot+1;/*尾递归*/}}//
首先:尾递归是线性递归的子集,属于线性递归。具体概念请参阅各大高校出版的书籍。作者把概念搞错了
其次,上文所举的第二个例子中在TailRescuvie(n-1, 1)没有计算出来之前,是不能return的。也就是说递归过程和第一个例子是差不多的,根本没有节约资源,甚至更浪费。
其实,编译器会很容易的对尾递归使用跳转语句进行优化,其实是可以return的。
尾递归就是把当前的运算结果(或路径)放在参数里传给下层函数,深层函数所面对的不是越来越简单的问题,而是越来越复杂的问题——因为参数里带有前面若干步的运算路径。对于阶乘而言,越深并不意味着越复杂。
从时间和空间效率上看,尾递归和传统递归差不多。递归运算效率低主要是分支巨大,像阶乘这类单分支的递归,效率并不低。递归运算的深度和运算总量大致成指数关系,return多次并不会造成显著的性能损失。
一言以蔽之,传统递归越深,距离目标越近;尾递归越深,距离起点越远。
尾递归适用于运算对当前递归路径有依赖的问题,传统递归适用于运算对更深层递归有依赖的问题。
/**************************************************************************************************/
第二作者对第二个例子的解释上有点不全面,尾递归的效果就是去除了将下层的结果再次返回给上层,需要上层继续计算才得出结果的弊端,如果读者仔细观看第二例子就可以看出,其实每个递归的结果是存储在第二个参数a中的,到最后一次计算的时候,会只返回一个a的值,但是因为是递归的原理虽然仍然要返回给上层,依次到顶部才给出结果,但是不需要再做计算了,这点的好处就是每次分配的内存不会因为递归而扩大。
在效率上,两者的确差不多。
OK,本文到此结束,希望对大家有所帮助。