递归函数简单的理解就是在不停地调用自己,如果不懂请参照“讲解”。
其实递归函数在使用时只需要明确一点:我写这个函数是干嘛用的,比如在用递归写计算N!的C语言程序时,只需要明确我写的函数是用来计算当前传入参数N与它前面!否则程序就会一直递归,直到栈溢出。
int
F
//递归函数
c语言函数递归
C语言函数是一种函数,用来编译C语言,一般包括字符库函数,数学函数,目录函数,进程函数,诊断函数,操作函数等。
C语言中的递归函数写法
递归定义
一个函数在它的函数体内直接或间接地调用自身称为函数的递归调用,而这种函数被称为递归函数。
直接调用:是指函数直接调用自己。
间接调用:是指函数在递归函数调用的下层再调用自己。
例:直接调用,Function1()->调用Function1()
间接调用,Function1()->调用Function2()->Function2()->调用Function1()
讲解
递归函数简单的理解就是在不停地调用自己,如果不懂请参照 “讲解” 。
其实递归函数在使用时只需要明确一点:我写这个函数是干嘛用的,比如在用递归写计算N!的C语言程序时,只需要明确我写的函数是用来计算当前传入参数N与它前面(N – 1)! 的乘积,写起来就会很简单。
而且要明确一点,那就是:递归调用的时候必须要有终止条件,也就是递归终点。否则程序就会一直递归,直到栈溢出。(不用纠结,深入学习后就会知道)
例子
一 、用递归算法计算 N 的阶乘。
#includeint F( int n ) //递归函数
{
longsum; //if(n == 0 || n == 1) //递归终点。return1;
else
{
sum = n * F( n – 1 );
}
returnsum; //函数返回sum的值。
}
int main()
{
int n;
scanf(“%d”, &n); //输入n
printf(“%d! = %d\n”, n, F(n));
return0;
}
这是一个很简单的递归程序,但是包含递归的要素:
递归函数参数的设置与变化,如 sum = n * F(n – 1) 中的 n-1。在别的题中,我们要去找到那个递推公式,然后合理设置参数,就能很快的写出递归函数。
递归终点的设置,如 if(n == 0 || n == 1) return 1; 就是很标准的递归终点。在写递归函数时,我们必须先想好函数的递归终点,然后才能写递归函数。
函数的返回值,如本道题中的 return sum; 再别的题目中,要注意考虑到所有的情况,稍微复杂一点题目就很容易漏掉某种情况,然后没有返回值。
同时补充一点函数的知识,在定义函数的时候,原则上函数的类型就是返回值的类型,但是如果类型不一样,会强制类型转换为定义函数地类型的值然后返回。
二 、贪吃的猴子。
觉得上面的例子很简单,那么就让我们看一道稍微难一点的递归题。
有一只猴子,第一天摘了若干个桃子 ,当即吃了一半,但还觉得不过瘾 ,就又多吃了一个。第2天早上又将剩下的桃子吃掉一半,还是觉得不过瘾,就又多吃了两个。以后每天早上都吃了前一天剩下的一半加天数个(例如,第5天吃了前一天剩下的一般加5个)。到第n天早上再想吃的时候,就只剩下一个桃子了。
输入:
天数n
输出:
第一天的桃子个数
提述:要先建立递推公式。
首先,就像我之前说的,明确我们写的递归函数是用来干嘛的,然后写出递推公式,明确递归终点,再写出递归函数。这道题就解决了。
那么,我们写的递归函数是用来干嘛的?根据题意,猴子每天吃掉前一天的一半加上天数个桃子。
所以我们写的递归函数就是计算第n天时剩余的桃子个数。然后建立递推公式:第 n 天剩余的桃子个数 =2*( 第 n+1 天剩余桃子数+ n )。
递归终点就是最后一天剩余桃子数为 1。然后我们就可以开始写递归函数了。
#includeint n; //定义全局变量n,记录输入天数int Taozi( int day ) //递归函数。
{
int num;
if( day == n )
{
return1; //递归终点。
}
else
{
num = 2 * ( Taozi( day + 1 ) + day ); //递推公式
}
return num; //返回num的值
}
int main()
{
int num; //此处num是局部变量,与递归函数中的num 意义不同scanf(“%d”, &n); //输入全局变量n的值
num = Taozi( 1 ); //因为是从第一天开始算,传入的参数值为 1。if(num > 1)
printf(“The monkey got %d peaches in first day.\n”, num);
elseprintf(“The monkey got %d peach in first day.\n”, num);
}
这题因为递推公式不同会有很多写法,不一一列举。 参考上面的提示,好好想一下这个过程,以便更好的理解递归的思想。接下来我会在列举几道递归的题,你们可以好好的琢磨一下这个过程。
三 、求数列的前n项和。
请使用递归算法求下列序列的前n项之和。
1 + 1/2 – 1/3 + 1/4 -1/5 ……
输入:
n
输出:
序列的前n项和(精确到小数点之后第6位)
像之前一样,我们来分析一下这个问题:我们写递归函数是用来干嘛的?这题很显然,是用来计算 1 / n 与 1 / (n – 1)的和,为什么是 n – 1 不是n + 1 ? 其实都是可以的,只是所得到的递推公式不一样,递归终点不一样。而这题我们从后往前加,递推公式很容易得到,递归终点也较简单。所以递归终点就是 1 。
注意:奇数项和偶数项的符号不一样,我们需要判断一下。
#include #include double plus(int x) // 这是一个返回值为浮点数的函数,写在后面的话要进行函数申明。
{
doublesum = 0;
if(x == 1) // 递归终点
{
return1;
}
else
{
if(x % 2 == 0) //当为偶数项时,符号为正sum = 1.0 / x + plus(x – 1);
else//当为奇数项时,符号为负(首项除外)sum = -1.0 / x + plus(x -1);
}
returnsum;
}
int main()
{
doublesum = 0;
int n = 0;
scanf(“%d”, &n);
sum = plus(n);
if(sum != 1)
printf(“%06lf\n”, sum);
else
printf(“1\n”);
return0;
}
四 、子串反向
请编写一个递归函数 reverse(char str[], int start, int end ) ,该函数的功能是将串 str 中下标从 start 开始到 end 结束的字符颠倒顺序。假设 start 和 end 都在合理的取值范围。
例如:
执行前:str[]=”0123456”;start=1 ;end=4
执行后:str[]=”0432156”
要求在该函数中没有循环。
分析:这题和之前的有些不一样,是对字符串操作的,那我们如何建立递推公式呢?
我们想,要从start到end调换,那么我们可以从两头向中间依次进行对调,那么递归的终点就是当指针相交或相等的时候,返回。
这样我们就可以实现字符串的对调。
#include #include #include voidreverse(char *str, int start, int end)
{
int t;
for(t = 0; str[t] != ‘\0’; t++); //计算字符串的长度//也可以 t = strlen(str);char temp; //中间变量if(end > t)
//当给的end超过字符串长度时,end直接变为t-1,end是下标所以减一
end = t – 1;
if(end <= start)
{
return; //递归终点
}
else
{
temp = str[start];
str[start] = str[end];
str[end] = temp; //交换字符reverse(str, start + 1, end – 1); //递归调用
}
return;
}
int main( )
{ charstr[100];
int start, end;
gets(str);
scanf(“%d %d”, &start, &end);
reverse( str, start, end );
printf(“%s\n”, str);
return0;
}
这道题虽然和上面的不一样,但是所用的递归思想是一样的,写递归函数的方式也相同。只不过没有了参数。
五 、回文字符串。
有一种特殊形式的字符串,其正反序相同,被称为“回文字符串”。例如LeveL就是一个回文字符串。
输入:
字符串
输出:
Yes或者No
说明:
如输出Yes,说明输入的字符串是一个回文字符串
输出No,说明输入的字符串不是一个回文字符串
请使用递归算法实现。
这道题相比上面的那道题还要简单一点,如果看了上面的题你有所收获的话,那么这道题一定不在话下。
那我们来看看吧,这道题是一道判断题,判断是否为回文串。操作和上面那题基本类似,就是比较首位往中间相对应的字符是否相同。但是递归终点我们可以用另一种表示方法,就是当我们所判断的子字符串的长度为 0 或 1 时,结束递归。具体我们看代码。
#include#includeint Huiwen( char *p , int n ) // n是代表字符串长度的参数
{
if(n == 1 || n == 0)
return1;
else
{
if( *p == *(p + n – 1) ) //判断对应位置的字符是否相同
{
return Huiwen( p + 1, n – 2 );
//这里返回的是下一次调用的返回值,这样只有当所有对应字符相同时才返回 1。
}
elsereturn0;
}
}
int main()
{
char arr[10000] = {0};
int n;
gets( arr );
n = strlen( arr );
if( Huiwen( arr, n) )
{
printf(“Yes\n”);
}
else
{
printf(“No\n”);
}
return0;
}
看完是不是觉得递归的写法多种多样?是的,不同的参数设置,不同的递推公式,不同的递归终点都会让写出来的递归程序不一样。但是里面所含的递归思想是一样的。明确那几点,写出一个递归程序其实很简单。
但是不要看到题就想用递归做,
所有的递归算法都可以用非递归算法写出,多想想们也许会有不一样的解题方法。
递归其实并不难,就那几步而已!
C语言中的递归函数有什么用途?什么意义?
递归函数提供了不一样的思维方式,用他来解决往往程序要短小很多,思维也会很清晰。它很适合解决树中的一些问题,在编译原理中也可以经常看到。
它的主要的解决问题的思维是这样的:
先解决最基础的简单的问题;
然后把复杂的问题归结为较简单的问题或把较大的问题分解为较小的问题。
下面这小段程序是用递归写的用来求1到n所有这些正整数的和的:
int f(int n){
if(n==1) return 1;
return n+f(n-1);
}
第一句解决了最简单的问题,就是n==1的情况。接下去在求较复杂的f(n)的时候把它归结为较简单的问题f(n-1)。
用递归也有几个需要注意的问题:
1.程序总得要有机会让它退出来,不然会变成死循环。就象这里的第一句,而且一般来说位置也通常在第一句。
2.递归还有性能开销。一是因为函数调用时参数的入栈出栈操作。二是有些问题处理不当会出现重复计算(不是很老到的程序员经常会出这样的问题,导致性能有问题,然后说递归根本没实际意义)。
c语言函数的递归调用?
Fibonacci数由小到排列后具有以下特点:前二项均为1,从第三项时,每项等于前二项的和。编写函数funA(n),用于返回一个不小于n的最小的一个Fibonacci数。主函数如下:main(){intn;sca…
Fibonacci数由小到排列后具有以下特点:前二项均为1,从第三项时,每项等于前二项的和。编写函数funA(n),用于返回一个不小于n的最小的一个Fibonacci数。
主函数如下:
main()
{ int n;
scanf(“%d”,&n);
printf(“%d”,funA(n));
}
展开
是的,局部变量会新定义一次,不过仅局限于局部变量(全局变量和静态变量都是全局的,要是还没学暂时不用管)。
并不能说是“同时”,应该说是“同样”,时间上肯定是按照调用的先后顺序的。
递归确实会让程序变慢,但只是相对于不需要递归的等价代码。而且原因也不是内存分配导致的,而是因为函数调用产生的。
追问
我后面写的这个总是得到错误答案,我觉得我还是没搞明白,可以帮忙看一哈吗
递归实现计算 c语言
递归实现计算xn:输入实数x和正整数n,用递归函数计算xn的值。试编写相应程序。用递归函数计算xn(n>=1)的值。…
递归实现计算 xn :输入实数x和正整数n,用递归函数计算 xn 的值。试编写相应程序。用递归函数计算xn (n>=1)的值。
int rec(int x,int n)
{
if(n==0)
return 1;
else
return rec(x,n-1)*x;
}
int main()
{
int x,n;
printf(“请输入x和n\n”);
scanf(“%d%d”,&x,&n);
printf(“结果是:%d\n”,rec(x,n));
}
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的阶乘?
1、打开VC6.0软件,新建一个C语言的项目:
2、接下来编写主程序,首先定义用来求阶乘的递归函数以及主函数。在main函数里定义变量sum求和,调用递归函数fact(),并将返回值赋予sum,最后使用printf打印sum的结果,主程序就编写完了:
3、最后运行程序,观察输出的结果。以上就是C语言使用递归求阶乘的写法:
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。
C语言的函数调用是递归吗?
没记错的话,C语言中的函数直接或间接调用自己的过程叫递归
例如 有main函数,函数A,C。
直接调用型递归:main函数调用函数A,而A不能直接解决问题,所以改变参数后去再次调用函数A。
比如有三个人,人1说他比人2小1岁,人2说他比人3小一岁,人3说他10岁,求人1几岁。就需要递归解决,
简介调用就是main调用A,A调用C,C又需要调用A,作用循环解决问题后由A回到main。
C语言递归是什么意思
程序调用自身的编程技巧称为递归( recursion)。递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
C语言中的递归是什么意思
C语言中经常说的递归是什么意思呢
举例说明
要理解递归,首先你要理解递归
简单来说就是一个函数调用到了自己,就可以称为递归.下面是简单的求n!的例子:
#include
#include
int fac(int n)
{
if(n==0)return 1;
return n*fac(n-1);
}
void main()
{
printf(“%d\n”,fac(6));
}
C语言中递归函数是,非递归函数是?能否举例子?
直接或间接调用自已的函数就是递归函数,否则为非递归函数。如:
unsigned fun(unsigned x){
if(x==1 || x==0)
return 1;
return x*fun(x-1);
}
这个函数的体中出现了调用自己的语句fun(x-1);,所以是递归函数。
今天的文章c 语言编程 函数的递归,c语言函数递归-递归,C语言入门分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/30293.html