大橙子网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
C语言:递归求和求f(n)的值可以采用以下的代码:
创新互联建站专注于富平网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供富平营销型网站建设,富平网站制作、富平网页设计、富平网站官网定制、小程序开发服务,打造富平网络公司原创品牌,更为您提供富平网站排名全网营销落地服务。
#includestdio.h
int sum(int n)
{
if(!n)
return 0;
else
return n + sum(n - 1);
}
int main()
{
int n;
scanf("%d",n);
printf("%d\n",sum(n));
return 0;
}
扩展资料:
数学函数
char *ecvt(double value,int ndigit,int *decpt,int *sign),将浮点数value转换成字符串并返回该字符串
char *fcvt(double value,int ndigit,int *decpt,int *sign),将浮点数value转换成字符串并返回该字符串
char *gcvt(double value,int ndigit,char *buf),将数value转换成字符串并存于buf中,并返回buf的指针
char *ultoa(unsigned long value,char *string,int radix),将无符号整型数value转换成字符串并返回该字符串,radix为转换时
double _matherr(_mexcep why,char *fun,double *arg1p,double *arg2p,double retval),用户修改数学错误返回信息函数(没有必要使用)
unsigned int _clear87() 清除浮点状态字并返回原来的浮点状态
void _fpreset() 重新初使化浮点数学程序包
unsigned int _status87() 返回浮点状态字
参考资料来源:百度百科-C语言函数
递归函数:
编程语言中,函数Func(Type a,……)直接或间接调用函数本身,则该函数称为递归函数。递归函数不能定义为内联函数。
在数学上,关于递归函数的定义如下:对于某一函数f(x),其定义域是集合A,那么若对于A集合中的某一个值X0,其函数值f(x0)由f(f(x0))决定,那么就称f(x)为递归函数。
函数介绍:
在数理逻辑和计算机科学中,递归函数或μ-递归函数是一类从自然数到自然数的函数,它是在某种直觉意义上是"可计算的" 。事实上,在可计算性理论中证明了递归函数精确的是图灵机的可计算函数。递归函数有关于原始递归函数,并且它们的归纳定义(见下)建造在原始递归函数之上。但是,不是所有递归函数都是原始递归函数 — 最著名的这种函数是阿克曼函数。
其他等价的函数类是λ-递归函数和马尔可夫算法可计算的函数。
例子:
//代码1
void func()
{
//...
if(...)
func();
else
//...
}
条件:
一个含直接或间接调用本函数语句的函数被称之为递归函数,在上面的例子中能够看出,它必须满足以下两个条件:
1) 在每一次调用自己时,必须是(在某种意义上)更接近于解;
2) 必须有一个终止处理或计算的准则。
梵塔的递归函数:
//C
void hanoi(int n,char x,char y,char z)
{
if(n==1)
move(x,1,z);
else
{
hanoi(n-1,x,z,y);
move(x,n,z);
hanoi(n-1,y,x,z);
}
}
编程里面估计最让人摸不着头脑的基本算法就是递归了。很多时候我们看明白一个复杂的递归都有点费时间,尤其对模型所描述的问题概念不清的时候,想要自己设计一个递归那么就更是有难度了。今天我也花费了半个小时来搞明白二叉树的平衡性的递归模型,首先我不明白什么叫做平衡性,所以花费的时候大部分实在试探理解平衡性的含义。在搞明白的时候,我突然想到假如让我来设计,在我知道平衡性的前提下,我是否可以建立如此简洁的递归模型。为此,我遇到的问题是我们到底在什么情况下适用递归模型,并且递归模型如何建立。
数学都不差的我们,第一反应就是递归在数学上的模型是什么。毕竟我们对于问题进行数学建模比起代码建模拿手多了。 (当然如果对于问题很清楚的人也可以直接简历递归模型了,运用数模做中介的是针对对于那些问题还不是很清楚的人)
自己观察递归,我们会发现,递归的数学模型其实就是归纳法,这个在高中的数列里面是最常用的了。回忆一下归纳法。
归纳法适用于想解决一个问题转化为解决他的子问题,而他的子问题又变成子问题的子问题,而且我们发现这些问题其实都是一个模型,也就是说存在相同的逻辑归纳处理项。当然有一个是例外的,也就是递归结束的哪一个处理方法不适用于我们的归纳处理项,当然也不能适用,否则我们就无穷递归了。这里又引出了一个归纳终结点以及直接求解的表达式。如果运用列表来形容归纳法就是:
步进表达式:问题蜕变成子问题的表达式
结束条件:什么时候可以不再是用步进表达式
直接求解表达式:在结束条件下能够直接计算返回值的表达式
逻辑归纳项:适用于一切非适用于结束条件的子问题的处理,当然上面的步进表达式其实就是包含在这里面了。
这样其实就结束了,递归也就出来了。
递归算法的一般形式:
void func( mode)
{
if(endCondition)
{
constExpression //基本项
}
else
{
accumrateExpreesion /归纳项
mode=expression //步进表达式
func(mode) / /调用本身,递归
}
}
最典型的就是N!算法,这个最具有说服力。理解了递归的思想以及使用场景,基本就能自己设计了,当然要想和其他算法结合起来使用,还需要不断实践与总结了。
例如:返回一个二叉树的深度:
int depth(Tree t){
if(!t) return 0;
else {
int a=depth(t.right);
int b=depth(t.left);
return (ab)?(a+1):(b+1);
}
}
判断一个二叉树是否平衡:
int isB(Tree t){
if(!t) return 0;
int left=isB(t.left);
int right=isB(t.right);
if( left =0 right =0 left - right = 1 || left -right =-1)
return (leftright)? (right +1) : (left + 1);
else return -1;
}
上面这两个递归的难易程度就不一样了,第一个关于深度的递归估计只要了解递归思想的都可以短时间设计出来,但第二个估计就要长点时间了。纯递归问题的难易主要纠结于一些条件表达式的构造以及初值的设置(上面的为直接表达式值的设定)。
最后需要补充的是,很多不理解递归的人,总认为递归完全没必要,用循环就可以实现,其实这是一种很肤浅的理解。因为递归之所以在程序中能风靡并不是因为他的循环,大家都知道递归分两步,递和归,那么可以知道递归对于空间性能来说,简直就是造孽,这对于追求时空完美的人来说,简直无法接接受,如果递归仅仅是循环,估计现在我们就看不到递归了。递归之所以现在还存在是因为递归可以产生无限循环体,也就是说有可能产生100层也可能10000层for循环。例如对于一个字符串进行全排列,字符串长度不定,那么如果你用循环来实现,你会发现你根本写不出来,这个时候就要调用递归,而且在递归模型里面还可以使用分支递归,例如for循环与递归嵌套,或者这节枚举几个递归步进表达式,每一个形成一个递归。
本人学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)!,当n1时,这样我们又有了递归形式,又可以以递归算法设计程序了。(楼上已给出谭老的程序,我就不写了)。
我给出一种优化的递归算法---尾递归。
从我给出的第一算法可以看出,先进栈再出栈,递归的效率是很低的。速度上完全比不上迭代(循环)。但是尾递归引入了一个新的函数参数,用这个新的函数参数来记录中间值.
普通递归阶乘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。