-
2021-05-20 10:34:09
c语言递归函数的使用方法
发布时间:2020-06-11 09:39:53
来源:亿速云
阅读:157
作者:Leah
这篇文章给大家分享的是c语言递归函数的使用方法。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。
递归就是一个过程或 函数 在其定义或说明中有直接或间接调用自身的一种方法;递归函数就是直接或间接调用自身的函数,也就是自身调用自己的过程。
1.Fibonacci数
我们直到Fibonacci数的递推公式为:F(0)=F(1)=1,F(n)=F(n-1)+F(n-2) n>=2;
这个明显地给出了递归边界n=0或1的时候F(n)的值,和递归逻辑F(n)=F(n-1)+F(n-2),即递推公式.所以这个递归函数不难书写#includeusing namespace std;
int F(int n)//函数返回一个数对应的Fibonacci数{ if(n0 || n1)//递归边界
return 1; return F(n-1) + F(n-2);//递归公式}
int main(){ //测试
int n; while(cin >> n) cout << F(n) << endl;
return 0;
}
2.阶乘的递归公式:n*F(n-1)
代码如下:#includeusing namespace std;
int F(int n){ if(n==0)//递归边界
return 1;
return n*F(n-1);//递归公式}
int main(){ int n; cin >> n; cout << F(n) << endl;
return 0;
}
3.数组求和
给一个数组a[]:a[0],a[1],…,a[n-1]如何用递归的方式求和?
仍然是两个问题:递归边界和递归公式.
递归边界是什么?一时不容易想到,但是我们想到了求和,多个数的求和过程是什么,x,y,z,w手动求和的过程是什么?步骤如下:
x+y=a,任务变为a,z,w求和
a+z=b,任务变为b,w求和
b+w=c得出答案
思考一下,【得出答案】这一步为什么就可以得出答案呢?(废话?)是因为,一个数不用相加就能得出答案.
所以,递归的边界就是只有一个数.
所以,递归边界有了,那么递归公式呢?其实手动计算过程中,隐含了递归公式:
其中+为求两个数的和,F为求多个数的和的递归函数.代码如下:#includeusing namespace std;
int F(int a[],int start,int end){ if(start==end)//递归边界
return a[start];
return a[start] + F(a,start+1,end);//递归公式}
int main(){ int a[] = {1,2,3,4,5}; int s=0,e=4; cout << F(a,s,e) << endl;
return 0;
}
4.求数组元素最大值
手动求最大值的过程是什么,遍历+比较,过程如下:
例如,求3,2,6,7,2,4的最大值:先设置最大值max=-999999,然后将max和数组元素逐个(遍历)比较如果a[i]>max,则更新max的值为a[i],否则max不变,继续向后遍历,直到遍历结束.
max<3,则max=3
max>2,max=3不变
max<6,则max=6
max<7,则max=7
max>2,max=7不变
max>4,max=7不变
遍历结束,max=7为最大值.
和求和类似,递归的公式如下:
其中max为求两个数的较大值函数,F为求多个数的最大值的递归函数.代码如下:#includeusing namespace std;
#define max(a,b) (a>b?a:b)
int F(int a[],int s,int e){ if(s==e) return a[s]; else if(s+1 == e)//递归边界
return max(a[s],a[e]);
return max(a[s],F(a,s+1,e));//递归公式!!!}
int main(){ int a[] = {5,1,4,6,2}; int s = 0,e = 4; cout << F(a,s,e) << endl;
return 0;
}
以上就是c语言递归函数的使用方法介绍,详细使用情况还得要大家自己使用过才能知道具体要领。如果想阅读更多相关内容的文章,欢迎关注亿速云行业资讯频道!
更多相关内容 -
递归函数(C语言)
2020-05-04 23:02:54递归函数:可以简单的理解为函数自己调用自己(要用出口,让函数跳出递归,以免出现无限额递归即死循环) 递归由两部分构成:函数关系和出口 eg: 求1+2+3+4+5....+9的和?(利用递归函数) 分析;(1)函数...递归函数:可以简单的理解为函数自己调用自己(要用出口,让函数跳出递归,以免出现无限额递归即死循环)
递归由两部分构成:函数关系和出口
eg:
求1+2+3+4+5....+9的和?(利用递归函数)
分析;(1)函数关系f(n)=f(n-1)+n (2) 出口:f(1)=1;
代码:
-
浅谈递归函数—C语言
2021-01-30 16:15:56浅谈递归函数—C语言 目录:浅谈递归函数—C语言递归函数的概念例题:总结 递归函数的概念 递归函数的定义:函数在其函数体内直接或间接调用它本身,则称该函数为递归函数。 递归的两个必要条件:(1)存在限制条件...浅谈递归函数—C语言
递归函数的概念
- 递归函数的定义:函数在其函数体内直接或间接调用它本身,则称该函数为递归函数。
- 递归的两个必要条件:(1)存在限制条件,当满足这个限制条件的时候,递归便不再继续;(2)每次递归调用之后越来越接近这个限制条件。
- 递归的主要思想:通过少量程序来描述解决问题过程所需的多次重复计算,即所谓的大事化小。
- 拓展:每一次调用递归函数时,计算机都会为该函数重新分配新的内存空间,并且将原递归函数暂停(可以理解为开副本),然后现场保存一下,即利用堆栈保存暂定位置,以及参数值保存。
例题
编程离不开示例,我们现在以例题帮我们加深对递归函数理解。
1.计算n!(1×2×3×·······×n)
先来看看整个的代码:#include<stdio.h> int Fac(int n) { if (n <= 1)//0!=1 1!=1 return 1; else return n*Fac(n - 1);//递归函数,自己调用自己 } int main() { int n = 0; scanf("%d", &n);//存储用户输入的值 int ret = Fac(n); printf("%d\n", ret); return 0; }
我们以n=3为例子,来看看下面这张图的思路
要用递归我要先找到需要重复计算的部分:n*Fac(n - 1),以及递归函数的出口n <= 1,有了这两个我们才可以设计程序。拓展:每次调用递归函数,都会利用堆栈保存现场,以刚刚计算阶乘为例,其在堆栈保存如图所示,先入的放在最底下,这样返回的时候,程序就可以清晰的直到自己要去到什么位置,从什么位置继续执行程序,后面进入先出来,当然这是比较抽象理解,在计算机内部都是以二进制形式表示。
2. 计算斐波那契数
的确斐波那契数考虑到效率,较优解并不是以递归的形式,而是以迭代循环的形式计算,这里举例斐波那契数列只是为了了解递归。
首先理解什么是斐波那契数:1 1 2 3 5 8 13 21 34.........
从数学定义角度来看:
Fib(0)=1
F(1)=1
F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)
可以直观看出斐波那契数列在n>=2后其值为前两项之和
同样先看看代码:int Fib(int n) { if (n <= 2) return 1; else return Fib(n - 1) + Fib(n - 2); } int main() { int n = 0; scanf("%d", &n); int ret = Fib(n); printf("%d\n", ret); return 0; }
我们以n=3为例子,来看看下面这张图的思路:
要用递归我要先找到需要重复计算的部分:Fib(n - 1) + Fib(n - 2),以及递归函数的出口n <= 2,有了这两个我们才可以设计程序。
3.汉诺塔问题
汉诺塔游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置n个金盘,游戏目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。为了方便理解,用动态图来表示:(图片来源知乎)
用递归的思想,我们要找到递归设计的两个重要部分:(1)重复部分,即自相似部分;(2)递归的出口。
(1)重复部分:不难发现,圆盘移动分三步:
第一步 把n-1个圆盘从A杆经C杆移动到B杆;
第二步 将A杆上第n个圆盘移动到C杆;
第三步 然后再将n-1个圆盘从B杆经A杆移动到C杆。
同理移动n-1个圆盘与移动n个圆盘是相识的,但是又有细微的不同,就是圆盘的插入杆变化了。所以我就先制定函数的参数:
int hanoi(int n, char A, char B, char C)//hanoi 汉诺塔
//n表示圆盘数
//上式子可以表示为将n个圆盘从A经B移动到C提取重复部分:
hanoi(n - 1, A, C, B)
//将n-1个圆盘从A经C移动到Bmove(A, C);
//将第n个圆盘从A移动到Chanoi(n - 1, B, A, C)
//将n-1个圆盘从B经A移动到C(2)递归函数的出口:
但N=1 时 ,只剩下一个圆盘直接移动到C杆就可以
move(A, C)
//本质是打印:A=====> C#include <stdio.h> int count = 0;//计算移动次数 void move(char x, char y) { printf("%c =====> %c\n", x, y); count++; } int hanoi(int n, char A, char B, char C)// n表示圆盘个数,A,B,C为三个杆子,表示从A经由B移动到C { if (n == 1) move(A, C); else { hanoi(n - 1, A, C, B); move(A, C); hanoi(n - 1, B, A, C); } } int main() { int n; printf("请输入圆盘数:\n"); scanf("%d", &n); count=hanoi(n,'A','B','C'); printf("总共移动%d次",count); return 0; }
总结
- 递归程序设计的实质:把一个复杂的问题分解成若干子问题来处理时,其中某些子问题与原问题有相同的特征属性,则可以利用和原问题相同的分析处理方法(注意原问题与子问题能很好衔接)。
- 在设计递归函数时候,要将每个递归函数看成简单的操作, 不要想得过于复杂。
-
C语言递归函数C语言递归函数C语言递归函数
2015-11-09 23:42:15//用递归函数来计算N的阶乘 double factorial(int n) { double result; if(n) { printf("输入错误\n"); } else if(n==1 ||n==0) { result=1; } else { result=factorial(n-1)*n; //n=5 5-1=4 4*5... -
【C语言】函数递归(详解)
2022-01-12 21:11:18函数递归思想函数递归
程序调用自身的编程技巧称为递归 recursion)
函数自己调用自己就是递归
你也可以理解成是一种嵌套结构,但递归分为俩部分,第一是“递”,进入嵌套结构。第二是”归“,最终会一步一步返回。第一次接触递归都会很懵,慢慢理解这个过程就明白了。
什么是递归?
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接
调用自身的
一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,
递归策略
只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的主要思考方式在于:把大事化小
递归的俩个必要条件
代码引例1
接受一个整型值(无符号),按照顺序打印它的每一位。
例如:
输入:123,输出 1 2 3
参考代码:
#include <stdio.h> void print(int n) { if(n>9) { print(n/10); } printf("%d ", n%10); } int main() { int num = 123; print(num); return 0; }
运行结果如下:
我们要怎么理解这个函数递归的实现呢
我们可以采用画图方式理解这个过程
所以我们可以看到,递归必须满足俩个必要条件:
1.存在限制条件,当满足这个限制条件的时候,递归便不再继续。
2.每次递归调用之后越来越接近这个限制条件。
题中的限制条件就是(n>9),当我们的n通过(n/10)越来越少,直至n=1,无法满足时,递归停止,并开始返回。
这里有一个重要点就是print(n/10),如果没有这个条件,换成print(n)的话,n一直无法减小,一直进行递归。最后会导致
栈溢出
(Stack Overflow)。栈溢出(Stack Overflow)
关于栈溢出,我就先简单介绍一下栈
栈:栈是一种计算机系统中的数据结构,它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来),是一种特殊的线性表。栈的操作常用的有进栈(PUSH),出栈(POP),还有常用的标识栈顶和栈底。
可以把栈想象成一摞扑克牌一样,一张一张叠加起来。
而栈溢出呢是缓冲区溢出的一种,缓冲区溢出:简单的说,缓冲区溢出就是超长的数据向小缓冲区复制,导致数据超出了小缓冲区,导致缓冲区其他的数据遭到破坏,这就是缓冲区溢出。而栈溢出是缓冲区溢出的一种,也是最常见的。只不过栈溢出发生在栈,堆溢出发生在堆,其实都是一样的。
而在代码引例1中
系统分配给程序的栈空间是有限的,但是如果出现了死循环,或者(死递归),这样有可能导致一
直开辟栈空间,最终产生栈空间耗尽的情况,这样的现象我们称为栈溢出
合理使用递归
使用递归的宗旨是把大事化小
所以遇到问题时,我们应该明白是要把问题简单化,而不是习惯用递归,就一直用递归思考问题
我们应该清楚是不是用递归的思想会比较简单,或者换成递归的思想也可以实现,我们可以通过例题明白
代码引例3
求n的阶乘
用循环的方法,代码如下:
int main() { int n = 0; int ret = 1; scanf("%d", &n); //循环产生1~n的数字 int i = 0; for (i = 1; i <= n; i++) { ret = ret * i; } printf("ret = %d\n", ret); return 0; }
而采用递归的话,代码如下:
int fac(int n) { if (n <= 1) return 1; else return n * fac(n - 1); } int main() { int n = 0; scanf("%d", &n); int ret = fac(n); printf("%d\n", ret); return 0; }
很多人刚学递归,都是懂了,但不知道怎么用。
而这道题可以先用公式来理解题目,再来用递归就容易多了
再来对比一下函数的代码,是不是清晰明了呢
代码引例4
求第n个斐波那契数。(不考虑溢出)
代码如下:
int fib(int n) { if (n <= 2) return 1; else return fib(n - 1) + fib(n - 2); }
这道题同样我们也可以利用公式构造一个函数实现递归
具体思路如下:
解释要合理使用递归
通过以上俩个例题,我们可以发现俩个问题:
在使用 fib 这个函数的时候如果我们要计算第50个斐波那契数字的时候特别耗费时间。
使用 factorial 函数求10000的阶乘(不考虑结果的正确性),程序会崩溃。
为什么呢?
我们发现 fib 函数在调用的过程中很多计算其实在一直重复。
如果我们把代码修改一下:
int count = 0;//全局变量 int fib(int n) { if(n == 3) count++; if (n <= 2) return 1; else return fib(n - 1) + fib(n - 2);
最后我们输出看看count,是一个很大很大的值。
那我们如何改进呢?
在调试 factorial 函数的时候,如果你的参数比较大,那就会报错: stack overflow(栈溢出)
这样的信息。
那如何解决上述的问题:
-
将递归改写成非递归。
-
使用static对象替代 nonstatic 局部对象。在递归函数设计中,可以使用 static 对象替代
nonstatic 局部对象(即栈对象),这不仅可以减少每次递归调用和返回时产生和释放 nonstatic 对象的开销,而且 static 对象还可以保存递归调用的中间状态,并且可为各个调用层所访问
比如,下面代码就采用了,非递归的方式来实现:
//求n的阶乘 int factorial(int n) { int result = 1; while (n > 1) { result *= n ; n -= 1; } return result; } //求第n个斐波那契数 int fib(int n) { int result; int pre_result; int next_older_result; result = pre_result = 1; while (n > 2) { n -= 1; next_older_result = pre_result; pre_result = result; result = pre_result + next_older_result; } return result; }
提示:
-
许多问题是以递归的形式进行解释的,这只是因为它比非递归的形式更为清晰。
-
但是这些问题的迭代实现往往比递归实现效率更高,虽然代码的可读性稍微差些。
-
当一个问题相当复杂,难以用迭代实现时,此时递归实现的简洁性便可以补偿它所带来的运行时开销
结束语
本人是学c小白,这些是近期学习整理总结,有什么不对欢迎大家指正,我会继续努力,谢谢~!
-
-
C语言——函数的递归
2022-02-23 16:38:36函数的声明和定义函数...函数的递归 什么是递归呢?? 程序调用自身的编程技巧称为递归(recursion),递归作为一种算法在程序设计语言中广泛应用。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方... -
C语言递归函数(递归调用)详解[带实例演示]
2021-12-23 22:04:26递归函数不是C语言的专利,Java、C#、JavaScript、PHP等其他编程语言也都支持递归函数。 下面我们通过一个求阶乘的例子,看看递归函数到底是如何运作的。阶乘 n! 的计算公式如下: 根据公式编写如下的代码: ... -
关于C语言中的递归函数
2019-03-14 11:09:34递归实例: #include <stdio.h> void up_and_down(int); int main(void) { up_and_down(1); return 0; } void up_and_down(int n) { printf("Level %d: n location %p\n", n, &... -
C语言详解:函数递归专题
2021-08-17 14:19:32函数递归 函数递归的定义和优缺点 程序调用自身的行为就是递归。可以直接或间接的调用,本质是把复杂的问题转化为一个规模小的问题。递归一般只需少量的代码就可描绘出多次重复计算。其主要思考方式在于大事化小。 ... -
C语言函数的递归
2022-03-26 23:06:11文章目录一、递归函数的定义二、函数调用机制说明三、递归调用的形式 一、递归函数的定义 所谓递归函数是指一个函数的函数体中直接调用或间接调用了该函数自身的函数。 递归函数调用的执行过程分为两个阶段。 递推... -
C语言函数+递归
2019-06-15 15:14:20函数可以看作是根据传入信息(输入)及其生成的值或响应的动作(输出)来定义的“黑盒”。 1. 返回值return 返回值不一定是变量的值,也可以是任意表达式的值 实际得到的返回值相当于把函数中指定的... -
C语言中有关递归的练习题
2022-02-15 15:38:50C语言中有关递归的练习题 -
递归函数的用法(c语言)
2020-05-25 20:49:27递归函数的用法 ——依次输出一个数的每一位 题目1:输入一个数,依次输出它的每一位。 问题分析: 假如输出的字符串为“123”,我们建立一个函数print()。即print(123)。我们不难得到最后一位数3(3=123%10)。... -
C语言函数的递归和调用实例分析
2021-05-18 09:42:06一、基本内容:C语言中的函数可以递归调用,即:可以直接(简单递归)或间接(间接递归)地自己调自己。要点:1、C语言函数可以递归调用。2、可以通过直接或间接两种方式调用。目前只讨论直接递归调用。二、递归条件采用... -
c语言函数递归(简单的递归例子c语言)
2021-05-19 08:48:47若在main函数中调用hanoi(3,'A','B','c')运行结果 void move(char getone,char .分成三组: (一), 目的:将1号和... 在hanoi(2,'A', 'C', 'B')中递归调用如下: A-->C----hanoi(1,'A', 'B', 'C') A-->B----ha... -
c语言函数递归-递归,C语言入门
2021-05-22 05:19:47递归函数简单的理解就是在不停地调用自己,如果不懂请参照...intF//递归函数c语言函数递归C语言函数是一种函数,用来编译C语言,一般包括字符库函数,数学函数,目录函数,进程函数,诊断函数,操作函数等。C语言... -
c语言递归函数,求和,数列
2019-10-22 09:43:27//递归函数,正整数列 int f1(int n) //n 取n的值 { if( n == 1) { return 1; } return f1(n - 1) + 1; //1 2 3 4 5 6 7 8 9 } //递归函数,奇数数列 int f2(int n) //n 取n的值 { if( n == 1) { ... -
阶乘 利用递归函数实现 c语言 简单易懂
2021-04-04 18:16:48//通过传入n的值,来计算它的阶乘所得的数,并将所得的结果返回,并通过一个整形的变量来接收它 //函数返回变量的类型应该与接受它的变量的类型相一致 printf("%d!=%d", n, sum);//打印输出它计算后阶乘所得的值 ... -
c语言递归算法怎么实现
2021-05-22 04:53:06递归就是一个方法自己调用自己。在编程语言中,如果一个程序允许您在同一个函数中调用一个函数,那么它就被称为函数的递归调用。void recursion() {recursion();...递归函数对于解决许多数学问题非... -
C语言:递归求阶乘
2022-05-04 09:38:25递归函数的定义:一个函数在它的函数体内调用它自身称为递归调用,这种函数称为递归函数。递归函数就是反复调用其自己。递归函数要有两要素:1.递归表达式 2.终止条件 先引入一个例子:输入n,求n!。 分析: n!= ... -
c语言递归函数写法
2012-05-13 18:03:24c语言程序设计教程(第二版)谭浩强,经典例题,对于学习c语言有很大帮助 -
C语言 之递归函数
2016-08-23 15:03:43今天来总结一下关于递归函数的使用方面的问题。 递归函数就是在函数使用的时候自己调用自己,层层调用,来实现你想要的功能。 有两个最常用的例子,我们来写一下。 (1)计算阶乘 #include <stdio.h> ... -
什么是递归-C语言函数递归-嗨客网
2021-05-22 06:05:04C语言函数递归教程函数递归就是一个C语言函数递归条件执行一个函数时,就创建一个新的受保护的独立空间(新函数栈)。函数的局部递归必须向退出递归的条件逼近,否则就是无限递归了。当一个函数执行完毕,或者遇到... -
C语言学习-10-递归函数-猴子吃桃子
2021-12-21 16:38:26递归函数一定需要用到if判断,所以第十天,还剩下一个桃子为结束递归的标志,而第九天的桃子数可以进行逆推为:第十天的桃子数一加一的综合乘上二,也就是说 某一天的桃子数=后一天的桃子数加一再乘上二。 三、源码 ... -
C语言用递归函数求1累加到100求和
2021-05-14 08:25:32C语言用递归求1累加到100求和要实现的功能如下完整源代码实现如下 要实现的功能如下 1+2+3+…+100,用递归实现 完整源代码实现如下 #include <stdio.h> int x = 0; int function(int num); int main() { int ... -
c语言用递归函数求数组逆序
2020-07-06 15:50:39#include <stdio.h> void Reverse_num(int *a,int num1,int num2); void swap(int *a,int *b); int main() { int array[10]={0,1,2,3,4,5,6,7,8,9};...printf(“逆序前的数组为\n”);...printf(“逆序 -
c语言递归函数实现求最大公约数(Euclid算法)
2020-10-11 21:16:451、编写递归函数求两个正整数a和b的最大公约数(GCD,Greatest Common Divisor),使用Euclid算法: 如果a除以b能整除,则最大公约数是b。 否则,最大公约数等于b和a%b的最大公约数@[TOC](这里写自定义目录标题) #... -
C语言 递归函数实现二分查找
2021-08-19 10:46:27C语言 递归函数实现二分查找 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。 新的...