‘壹’ c语言怎么计算递归次数
递归就是有限次的嵌套调用函数本身,要知道递归的次数,就找出调用中变化量到结束调用的判断点,这之间的变量变化次数等于顺推次数,返回个数等于顺推次数,这样就可以计算出总的次数
‘贰’ c语言中的递归
本人学c++,c的语法已经淡忘了,但是递归不管什么语言都是一个原理
其实简单一点来说就像数学里面的数列的通项公式:
例如一个数列是2,4,6,8,10......
很容易就可以得到通项公式是a[n]=2*n n是大于0的整数
你肯定学过这个数列的另外一种表示方式就是: a[1]=2, a[n]=a[n-1]+2 n是大于1的整数
其实这就是一个递归的形式,只要你知道初始项的值,未知项和前几项之间的关系就可以知道整个数列。
程序例子:比如你要得到第x项的值
普通循环:
for(int i=1; i<=n; i++)
if (i == x)
cout << 2*i; /*cout 相当于 c里面的printf,就是输出.*/
递归:
int a(int x) {
if (x = 1)
return 2; /* 第一项那肯定是2了,这个也是递归的终止条件! */
else return a(x-1)+2; /* 函数自身调用自身是递归的一个特色 */
比如x=4,那么用数学表示就是a(4)=a(3)+2=(a(2)+2)+2=((a(1)+2)+2)+2
其实递归方法最接近自然,也是最好思考的一个方法,难点就是把对象建模成递归形式,但是好多问题本身就是以递归形式出现的。
普通递归就是数据结构上的堆栈,先进后出。
例如上面x=4,把a(4)放入栈底,然后放入a(3),然后a(2),a(1),a(1)的值已知,出栈,a(1)=2,a(2)出栈a(2)=a(1)+2=2+2=4,a(3)出栈a(3)=a(2)+2=(a(1)+2)+2=6,a(4)出栈a(4)=a(3)+2=(a(2)+2)+2=((a(1)+2)+2)+2=8
再比如楼上的阶乘例子,当n=0 或 1时,0!=1,1!=1,这个是阶乘的初始值,也是递归的终止条件。然后我们知道n!=n*(n-1)!,当n>1时,这样我们又有了递归形式,又可以以递归算法设计程序了。(楼上已给出谭老的程序,我就不写了)。
我给出一种优化的递归算法---尾递归。
从我给出的第一算法可以看出,先进栈再出栈,递归的效率是很低的。速度上完全比不上迭代(循环)。但是尾递归引入了一个新的函数参数,用这个新的函数参数来记录中间值.
普通递归阶乘fac(x),就1个x而已,尾递归用2个参数fac(x,y),y存放阶乘值。
所以谭老的程序就变成
// zysable's tail recursive algorithm of factorial.
int fac(int x, int y) {
if (x == 1)
return y;
else return fac(x-1, y*x);}
int ff(int x) {
if (x == 0)
return 1;
else return fac(x,1);}
对于这个程序我们先看函数ff,函数ff其实是对fac的一个封装函数,纯粹是为了输入方便设计的,通过调用ff(x)来调用fac(x,1),这里常数1就是当x=1的时候阶乘值了,我通过走一遍当x=3时的值即为3!来说明一下。
首先ff(3),x!=0,执行fac(3,1).第一次调用fac,x=3,y=1,x!=1,调用fac(x-1,y*x),新的x=2,y=3*1=3,这里可以看到,y已经累计了一次阶乘值了,然后x还是!=1,继续第三次调用fac(x-1,y*x),新的x=1,y=2*3=6,然后x=1了,返回y的值是6,也就是3!.你会发现这个递归更类似于迭代了。事实上我们用了y记录了普通递归时候,出栈的乘积,所以减少了出栈后的步骤,而且现在世界上很多程序员都在倡议用尾递归取消循环,因为有些在很多解释器上尾递归比迭代稍微效率一点.
基本所有普通递归的问题都可以用尾递归来解决。
一个问题以递归来解决重要的是你能抽象出问题的递归公式,只要递归公式有了,你就可以放心大胆的在程序中使用,另外一个重点就是递归的终止条件;
其实这个终止条件也是包含在递归公式里面的,就是初始值的定义。英文叫define initial value. 用普通递归的时候不要刻意让自己去人工追踪程序,查看运行过程,有些时候你会发现你越看越不明白,只要递归公式转化成程序语言正确了,结果必然是正确的。学递归的初学者总是想用追踪程序运行来让自己来了解递归,结果越弄越糊涂。
如果想很清楚的了解递归,有种计算机语言叫scheme,完全递归的语言,因为没有循环语句和赋值语句。但是国内人知道的很少,大部分知道是的lisp。
好了,就给你说到这里了,希望你能学好递归。
PS:递归不要滥用,否则程序极其无效率,要用也用尾递归。by 一名在美国的中国程序员zysable。
‘叁’ 如何计算递归
举个简单的例子吧,1*2*3*4*5 ;
#include< iostream >
using namespace std;
int Fun( int val )
{
if( n > 1 )
return val * Fun( val - 1 ); // 最难理解的相信就是这一步吧
return val;
}
int main()
{
cout << Fun( 5 ) << endl ;
return 0;
}
首先,第一次调用Fun函数时,val == 5;
所以好好分析一下这段代码
if( val > 1 )
return val * Fun( val - 1 ) ;
第一次调用时 val == 5, 条件成立, 函数返回 val( 等于5那个 )乘以用实参 4 ( 也就是val - 1 的值 ) 调用的那个函数的返回值( 也就是自身 )...
看到这里先不要头晕, 这只是第一步,还有很多步调用,其实跟循环是差不多的.
函数调用有一个返回值, 如果返回值是一个表达式,就先求解表达式的值再返回,被函数返回时从调用函数处的下一个语句继续执行,如果没有理解C语言的这两句话,这就很难理解递归了.
下面是整个程序的流程
1, 用 val == 5 调用 Fun, 执行到 if 语句, 条件成立 执行 return val * Fun( val - 1 ), 由于函数调用操作符 () 优先级高于算术操作符, 因此表达式的求解顺序是先调用函数, 再 用 val * 返回值;
2, 用 val == 4 的值调用 Fun,后面的步骤和用 val == 5调用 Fun 的步骤是一样的;
3, 用 val == 3 的值调用 Fun;
4, 用 val == 2 的值调用 Fun;
5, 用 val == 1 的值调用 Fun, 这时的 if 语句条件不成立, 于是执行后面的
return val 的值( == 1 );
6, 那这个 val == 1 的值返回到哪里去了呢? 刚接触递归的人可能会很容易联想到是 main 函数调用 Fun 的, 那这个值也返回到 main 函数中去了. 其实不是,返回值为1的Fun函数是谁调用的?是 val == 2 时的Fun函数调用的,也就是第4步的if 语句后面的表达式是 return 2 * Fun( 2 - 1 ),理解这点就好办了,第六步就开始求解前面还没执行的算术操作( 由于函数调用操作符 () 优先级高于算术操作符, 因此表达式的求解顺序是先调用函数 ).也就是把第5步的返回值用于求解第4步时里的表达式;
7, 在上一步骤中,求解出 2 * Fun( val - 1 )的值, 又把它返回给它的调用者
,就是把值 3 返回至第3步;
8, 把第3步的得出的值返回第2步;
9, 把第2 步得出的值返回第1步;
10, 在第1步,记得这次调用是main函数调用的,因此返回到main函数中的cout << Fun( 5 ) << endl, 输出结果;
整个递归过程就完成了,可以看到递归也是一个循环,但它比一般的循环计算的步骤多了很多,所以它的效率普遍是比较低的,而且操作系统把每一次的调用装进一个栈中记录起来,它耗费的内存也是比较大的,在深层的递归调用或在递归函数中定义较大的数据容易造成栈溢出,但有时( 对初学者来说不见得 )用它来解决问题却能让代码清晰,容易编写.
‘肆’ c语言求递归次数
递归次数,设一个全局变量计数就可以了
int count = 0;
在move中添加 count++;
‘伍’ C语言怎么计算递归次数
perm1()函数中定义一个静态变量用于计数,调用该函数的时候计数器自增。显示函数多传入一个排列序号。如下所示:
void perm1(int *p,int n,int m)
{
void swap(int *data1,int *data2);
void output(int index,int *p,int n); //多传入一个排列序号
static s_cnt = 0;//计数器
int i;
s_cnt++;//计数器自增
if(m==(n-1)){
output(s_cnt,p,n);
}
else{
for(i=m;i<n;i++){
swap(&p[i],&p[m]);
perm1(p,n,m+1);
swap(&p[i],&p[m]);
}
}
}
void output(int index,int *p,int n)
{
printf("------------------\n");
printf("Index: %d", index);//显示序号
//printf("time=%d\n",m);
int i;
for(i=0;i<n;i++){
printf("p[%d]=%d\n",i,p[i]);
}
}
‘陆’ 用C语言的函数递归方法来求
#include <stdio.h>
#include <math.h>
void fun2(int m)
{
int k=0,a[10];
for(int i=2;i<m;i++)
if(m%i==0)
a[k++]=i;
for(int i=0;i<k;i++)
{
printf("%d",a[i]);
if(i!=k-1)
printf(",");
}
}
void fun1(int m)
{
if(m<2)
printf("%d is a prime number",m);
for(int i=2;i*i<=m;i++)
if(m%i==0)
fun2(m);
else
printf("%d is a prime number",m);
}
int main( )
{ int n;
scanf("%d",&n);
fun1(n);
return 0;
}
‘柒’ C语言函数递归计算
#include<stdio.h>
#include<stdlib.h>
intcount=0;
intfun(intx,intn)
{
count++;
if(n==2)
{
returnx*x;
}
elseif(n%2==0)
{
returnfun(x,n/2)*fun(x,n/2);
}
elseif(n%2==1)
{
returnfun(x,n-1)*x;
}
}
intmain(intargc,char*argv[]){
intsum=0,x,n;
printf("请输入xn的值(两数之间用空格间隔):");
scanf("%d%d",&x,&n);
sum=fun(x,n);
printf("%d递归调用了%d次",sum,count);
return0;
}
‘捌’ c语言函数递归的算法
这是一个递归调用fun(x)的算法。
首先会计算x=1时,因为x是int型,所以x/2==0,返回1,所以打印1.
然后再计算x=2时,这时返回x%2=0,所以打印0;
再计算x=4时,同样返回x%2=0,所以打印0;
最后计算x=8时,返回x%2=0,所以打印0。
所以屏幕输出的就显示1000 。
‘玖’ C语言中递归次数怎么输出
使用一个全局变量,在main中初始化,在递归的函数中将这个变量加一,在使用递归函数前把变量清零,使用递归函数后,这个变量值就是递归的次数。
‘拾’ c语言递归算法
用递归法计算n!
用递归法计算n!可用下述公式表示:
n!=1 (n=0,1)
n×(n-1)! (n>1)
按公式可编程如下:
long ff(int n)
{
long f;
if(n<0) printf("n<0,input error");
else if(n==0||n==1) f=1;
else f=ff(n-1)*n;
return(f);
}
main()
{
int n;
long y;
printf("\ninput a inteager number:\n");
scanf("%d",&n);
y=ff(n);
printf("%d!=%ld",n,y);
}
程序中给出的函数ff是一个递归函数。主函数调用ff 后即进入函数ff执行,如果n<0,n==0或n=1时都将结束函数的执行,否则就递归调用ff函数自身。由于每次递归调用的实参为n-1,即把n-1的值赋予形参n,最后当n-1的值为1时再作递归调用,形参n的值也为1,将使递归终止。然后可逐层退回。
下面我们再举例说明该过程。设执行本程序时输入为5,即求5!。在主函数中的调用语句即为y=ff(5),进入ff函数后,由于n=5,不等于0或1,故应执行f=ff(n-1)*n,即f=ff(5-1)*5。该语句对ff作递归调用即ff(4)。
进行四次递归调用后,ff函数形参取得的值变为1,故不再继续递归调用而开始逐层返回主调函数。ff(1)的函数返回值为1,ff(2)的返回值为1*2=2,ff(3)的返回值为2*3=6,ff(4)的返回值为6*4=24,最后返回值ff(5)为24*5=120。