6.C++函数递推递归
算法总结之递推与递归
算法总结之递推与递归递推算法递归算法⼤致包括两⽅⾯的内容:1)递归起点; 2)递归关系递推起点递归起点⼀般由题⽬或者实际情况确定,不由递归关系推出。
如果⽆法确定递归起点,那么递归算法就⽆法实现。
可见,递归起点是递归算法中的重要⼀笔。
递推关系递归关系是递归算法的核⼼。
常见的递归关系有以下⼏项:1)⼀阶递推;2)多阶递推;3)间接递推;4)逆向递推;5)多维递推。
下⾯通过栗⼦来详细介绍⼀下上述类别的递推关系。
1. ⼀阶递推在计算f(i)时,只⽤到前⾯项中的⼀项,如等差数列。
公差为3的等差数列,其递推关系为:f(i)=f(i-1)+3eg. 平⾯上10条直线最多能把平⾯分成⼏部分?分析:以直线数⽬为递推变量,假定i条直线把平⾯最多分成f(i)部分,则f(i-1)表⽰i-1条直线把平⾯分成的最多部分。
在i-1条直线的平⾯上增加直线i,易得i与平⾯上已经存在了的i-1条直线最多各有⼀个交点,即直线i最多被分成i段,⽽这i段将会依次将平⾯⼀分为⼆,即直线i将最多使平⾯多增加i部分。
所以,递推关系可表⽰为:f(i)=f(i-1)+i易得当0条直线时,平⾯为1部分。
所以f(0)=1为递推起点。
上述分析可⽤下⾯代码表⽰(c++):#define MAX 100int f[MAX] //存放f(i)int lines(int n){//输⼊n为直线数⽬//输出最多部分数int i;f(0)=1;for(i=1;i<=n;i++){f[i]=f[i-1]+3;}return f[i];}2. 多阶递推在计算f(i)时,要⽤到前⾯计算过的多项,如Fibonacci数列。
eg.求Fibonacci的第10项。
分析:总所周知,Fibonacci数列中的第n项等于第n-1项加上n-2项。
所以递推关系为f(i)=f(i-1)+f(i-2);且f[0]=f[1]=1。
C++代码如下:#define MAX 100int f[MAX];int fib(int n){//输⼊n为项数//输出第n个fib数int i;f[0]=0;f[1]=1;for(i=2;i<=n;i++){f[i]=f[i-1]+f[i-2];}return f[n]}3. 间接递推在计算f[i]时需要中间量,⽽计算中间量要⽤到之前计算过的项。
C++函数、递推、递归ppt课件
i = 7 s1 = 2 * (s2 + 1) ; s2 = s1 ;
// S(7) = 2 * (S(8) + 1) // s2 = s1 = S(7)
i = 6 s1 = 2 * (s2 + 1) ; s2 = s1 ;
// S(6) = 2 * (S(7) + 1) // s2 = s1 = S(6)
看一个简单的例子:
1 4
第九讲——函数、递推、递归
递归
有 5 个人坐在一起,问第 5 个人多少岁? 他说比第 4 个人 大两岁。问第 4 个人岁数,他说比第 3 个人大两岁。问第 3 个人,又说比第 2 个人大两岁。问第 2 个人,说比第 1 个人 大两岁。最后问第 1 个人,他说是 10 岁。请问第 5 个人多 大?
3
第九讲——函数、递推、递归
解题思路:
假设用 S(i) 表示第 i 天没吃之前的桃子数目;
则
S(1) 即为第 1 天所摘的桃子数; S(2) = S(1) * 1/2 – 1 第 2 天没吃之前的桃子数
S(3) = S(2) * 1/2 - 1 第 3 天没吃之前的桃子数
…
…
S(9) = S(8) * 1/2 - 1 第 9 天没吃之前的桃子数
= age(2) + 2 + 2 + 2 // c = age(2) + 2
= age(1) + 2 + 2 + 2 + 2;// c = 10;
2 2
计算年龄程序
第九讲——函数、递推、递归
2 3
第九讲——函数、递推、递归
递归算例(2)
用递归方法计算 n! 算法思路:
C语言中的递归函数应用
C语言中的递归函数应用递归函数在C语言中是一种非常重要且常用的编程技术,可以简化代码逻辑,实现程序的高效性和可维护性。
递归函数是指在函数中调用自身的函数,通过不断调用自身来解决问题,直到达到终止条件为止。
在C语言中,递归函数的应用非常广泛,比如在树的遍历、阶乘计算、斐波那契数列等方面都能看到递归函数的影子。
首先来看一个经典的递归函数示例,计算阶乘的函数:```cint factorial(int n) {if (n == 0) {return 1;} else {return n * factorial(n-1);}}```在上面的代码中,factorial函数通过调用自身来计算n的阶乘。
当n为0时,递归终止,返回1;否则,返回n与factorial(n-1)的乘积。
这种递归方式简洁而高效,使得代码更加易于理解。
另一个常见的应用是在树的遍历中,比如二叉树的先序、中序、后序遍历都可以通过递归函数实现。
以二叉树的中序遍历为例:```cvoid inorderTraversal(TreeNode* root) {if (root == NULL) {return;}inorderTraversal(root->left);printf("%d ", root->val);inorderTraversal(root->right);}```在上面的代码中,通过递归函数inorderTraversal实现了二叉树的中序遍历。
首先判断根节点是否为空,若为空则返回;否则,先递归遍历左子树,输出根节点的值,再递归遍历右子树。
这种递归方式简洁而直观,可以应用于各种树的遍历操作。
除此之外,递归函数还广泛应用于解决数学问题,比如求解斐波那契数列:```cint fibonacci(int n) {if (n == 0) {return 0;} else if (n == 1) {return 1;} else {return fibonacci(n-1) + fibonacci(n-2);}}```在上面的代码中,通过递归函数fibonacci实现了斐波那契数列的计算。
c 递归算法
c 递归算法
C语言中,递归是一种算法设计方法,它允许函数在自身调用中进行迭代。
通过将一个大问题分解为一个或多个规模较小的子问题,递归可以解决复杂的问题。
递归算法有以下主要特点:
1. 基本情况(Base Case):递归算法必须有一个或多个基本情况,也称为递归终止条件。
当达到基本情况时,递归将停止并返回结果,避免无限循环。
2. 递归调用:递归算法通过在函数内部调用自身来解决问题的规模更小的子问题。
每次递归调用都将原问题分解为规模较小的子问题,直到达到基本情况。
递归算法可以解决一些问题,但需要注意以下几点:
- 确保递归能够收敛到基本情况,避免无限递归导致栈溢出。
- 递归算法的执行效率可能较低,因为每次递归调用都会产生函数调用开销和栈空间的使用。
- 在设计递归算法时,需要合理选择递归终止条件和递归调用,以确保正确性和高效性。
以上是关于C语言中递归算法的一些基本概念和示例,希望对你有帮助。
c语言中的递归 (1)
c语言中的递归递归是一种常见的编程技巧,也是C语言中的重要概念之一。
通过递归,我们可以将一个复杂的问题分解成更小的子问题,从而简化解决方案。
在C语言中,递归函数是一种自己调用自己的函数,它可以通过不断调用自身来解决问题。
递归函数通常包含两个部分:基本情况和递归情况。
基本情况是指递归函数停止调用自身的条件,而递归情况则是指递归函数调用自身的情况。
在编写递归函数时,我们需要确保递归情况最终会达到基本情况,否则递归函数将陷入无限循环。
一个经典的例子是计算阶乘。
阶乘是指从1到某个正整数n的所有整数的乘积。
我们可以使用递归函数来计算阶乘。
首先,我们需要定义基本情况,即当n等于1时,阶乘的结果为1。
然后,我们定义递归情况,即当n大于1时,阶乘的结果为n乘以(n-1)的阶乘。
下面是一个使用递归函数计算阶乘的示例代码:```c#include <stdio.h>int factorial(int n) {if (n == 1) {return 1;} else {return n * factorial(n - 1);}}int main() {int n;printf("请输入一个正整数:");scanf("%d", &n);printf("%d的阶乘是%d\n", n, factorial(n));return 0;}```在上面的代码中,我们定义了一个名为factorial的递归函数,它接受一个整数n作为参数,并返回n的阶乘。
在递归情况中,我们调用了自身,并将n减1作为参数传递给递归函数。
当n等于1时,递归函数将返回1,从而达到基本情况。
递归函数的执行过程可以用一棵树来表示,这棵树被称为递归树。
每个节点表示一个函数调用,树的根节点表示初始函数调用,叶子节点表示基本情况。
通过递归树,我们可以更好地理解递归函数的执行过程。
然而,递归并不是解决所有问题的最佳方法。
C语言递归详细解答
C语言递归详细解答.txt喜欢我这是革命需要,知道不?!你不会叠衣服一边呆着去!以后我来叠!我一定要给你幸福,谁也别想拦着。
递归递归是设计和描述算法的一种有力的工具,由于它在复杂算法的描述中被经常采用,为此在进一步介绍其他算法设计方法之前先讨论它。
能采用递归描述的算法通常有这样的特征:为求解规模为N的问题,设法将它分解成规模较小的问题,然后从这些小问题的解方便地构造出大问题的解,并且这些规模较小的问题也能采用同样的分解和综合方法,分解成规模更小的问题,并从这些更小问题的解构造出规模较大问题的解。
特别地,当规模N=1时,能直接得解。
【问题】编写计算斐波那契(Fibonacci)数列的第n项函数fib(n)。
斐波那契数列为:0、1、1、2、3、……,即:fib(0)=0;fib(1)=1;fib(n)=fib(n-1)+fib(n-2) (当n>1时)。
写成递归函数有:int fib(int n){ if (n==0) return 0;if (n==1) return 1;if (n>1) return fib(n-1)+fib(n-2);}递归算法的执行过程分递推和回归两个阶段。
在递推阶段,把较复杂的问题(规模为n)的求解推到比原问题简单一些的问题(规模小于n)的求解。
例如上例中,求解fib(n),把它推到求解fib(n-1)和fib(n-2)。
也就是说,为计算fib(n),必须先计算fib(n-1)和fib(n-2),而计算fib(n-1)和fib(n-2),又必须先计算fib(n-3)和fib(n-4)。
依次类推,直至计算fib(1)和fib(0),分别能立即得到结果1和0。
在递推阶段,必须要有终止递归的情况。
例如在函数fib中,当n为1和0的情况。
在回归阶段,当获得最简单情况的解后,逐级返回,依次得到稍复杂问题的解,例如得到fib(1)和fib(0)后,返回得到fib(2)的结果,……,在得到了fib(n-1)和fib(n-2)的结果后,返回得到fib(n)的结果。
c语言使用递归函数
递归函数是一种特殊的函数,它调用自身来解决问题。
在C语言中,递归函数可以通过以下方式实现:
1. 定义一个函数,该函数返回一个值,或者没有返回值(void)。
2. 在函数的函数体中,使用return语句或break语句来结束函数的执行。
3. 在函数的函数体中,调用自身,将问题的规模减小,直到问题能够直接解决为止。
下面是一个简单的递归函数示例,该函数计算一个数的阶乘:
```c
#include <stdio.h>
int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
int main() {
int n = 5;
int result = factorial(n);
printf("%d! = %d\n", n, result);
return 0;
}
```
在上面的代码中,factorial()函数是一个递归函数。
当n等于0时,函数返回1。
否则,函数返回n乘以factorial(n-1)的结果。
在main()函数中,我们调用factorial()函数来计算5的阶乘,并将结果打印到控制台上。
C语言中的递归函数如何实现?
C语言中的递归函数如何实现?在 C 语言的世界里,递归函数是一种强大而又神秘的工具。
它就像是一把双刃剑,用得好可以让程序简洁高效,用不好则可能让程序陷入无限的循环和错误之中。
那么,究竟什么是递归函数,又该如何实现它呢?首先,我们来理解一下递归函数的概念。
简单来说,递归函数就是一个在函数内部调用自身的函数。
这听起来可能有点绕,但其实举个例子就很好理解。
比如计算阶乘,阶乘的定义是 n 的阶乘等于 n 乘以(n 1) 的阶乘,当 n 为 0 或 1 时,阶乘为 1。
我们可以用递归函数来实现计算阶乘的功能:```cinclude <stdioh>int factorial(int n) {if (n == 0 || n == 1) {return 1;} else {return n factorial(n 1);}}int main(){int num = 5;int result = factorial(num);printf("%d 的阶乘为%d\n", num, result);return 0;}```在这个例子中,`factorial` 函数就是一个递归函数。
当`n` 为 0 或1 时,函数直接返回 1,这就是递归的终止条件。
否则,它就通过`n factorial(n 1)`来调用自身,不断地将问题规模缩小,直到达到终止条件。
实现递归函数,有两个关键的要点。
一是要有明确的终止条件。
就像上面的阶乘例子,如果没有终止条件,函数就会一直调用自身,永无止境,最终导致栈溢出错误。
终止条件是递归能够正确结束的保障,它让函数在适当的时候停止递归调用,返回结果。
二是要能够将问题逐步分解为更小的、相似的子问题。
还是以阶乘为例,计算 n 的阶乘,就可以分解为计算(n 1) 的阶乘,然后再乘以n。
通过不断地分解问题,最终达到终止条件,从而得到结果。
再来看一个经典的例子——斐波那契数列。
斐波那契数列的定义是前两个数为 0 和 1,从第三个数开始,每个数都是前两个数之和。
C语言-递推递归
2012-3-20
12
伯努利装错信封问题
某人给不同地址不同姓名的n位朋友写信,信 某人给不同地址不同姓名的n位朋友写信, 信封都分别写好了。请问:所有信笺、 笺、信封都分别写好了。请问:所有信笺、 信封全都装错的情况有多少种? 信封全都装错的情况有多少种? 信封:A B 信封: 信笺: 信笺:a b C c D d E e F f … …
信封:A B C D E F … 信封: 信笺: 后 封也都装错 封也都装错) 信笺:b a (后n-2封也都装错
错误2: 错误 :
信封: 信封:A B C D E F … 信笺: 封也都装错) 信笺:b 非a (后n-2封也都装错 后 封也都装错
2012-3-20
装错情况 种数Sn-1
14
Sn= (n-1)(Sn-1+ Sn-2)
A B C
2012-3-2024 Nhomakorabea递归
• 当有n个盘子需要移动时,通常的方法如下: (1)把A柱上n-1个盘子借助C柱移动到B柱上。只有 这样,C柱才能为空,则A柱上的第n个盘子(最大 的那个)才能直接移动到C柱上。 (2)将A柱上的剩下的第n个盘子移动到C柱上。这个 盘子已最后到位,不需要再移动了。 (3)再将B柱上的n-1个盘子借助A柱移动到C柱。
2012-3-20 19
递归
f (1) = 1 n =1 f ( n) = f ( 2) = 1 n=2 f (n) = f (n − 2) + f (n − 1) n ≥ 3
int func(int n) /*求斐波那契数列的第n个数*/ { int result; if(n==1) result=1; else if(n==2) result=1; else result=func(n-1)+func(n-2); /*递归*/ return result; } 2012-3-20
C语言的递归函数详解
C语⾔的递归函数详解⽬录函数递归什么是递归?递归的俩个必要条件代码引例1栈溢出(StackOverflow)合理使⽤递归代码引例3代码引例4解释要合理使⽤递归总结函数递归程序调⽤⾃⾝的编程技巧称为递归 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)。
递归与递推
visit(t);
m-search(l.right); end; end;
精品PPT
三、递归算法(suàn fǎ)的执行过程
n!1n(n1)!
n0 n0
主程序
=120
Fac(5)
=24
5*Fac(4)
end;
精品PPT
n皇后(huánghòu)问题
如何记录某个数字是否已经被使用过呢?很容 易想到可以用集合或者一维数组来实现。 比如我们(wǒ men)用一维数组hash[1..n]来记 录的话 hash[i]=1代表i已经被使用过 hash[i]=0代表i没有被使用过
同时我们(wǒ men)使用一个一维数组 result[1..n]来记录生成的全排列
精品PPT
汉诺塔问题(wèntí)
输入(shūrù):3 输出:
A->C A->B C->B A->C B->A B->C A->C
精品PPT
汉诺塔问题(wèntí)
只有一个盘子(pán zi)的移动:A C 两个盘子(pán zi)的移动:A B,A C,
BC n个盘子(pán zi)的移动(n>2): 将上面的n-1个盘子(pán zi)看成一个整体,
end.
精品PPT
四、应用(yìngyòng)举例—汉诺塔 问题
如图所示,我们有三根柱子(A、B、C)和若干大小 各异的圆盘,一开始的时候,所有圆盘都在A柱上, 且按照从小到大的顺序排列整齐(小的在上,大的在 下),现在请你把所有的圆盘从A柱搬到C柱上去。 在搬动的时候,一次只能将某柱最顶端的一个(yī ɡè) 圆盘移动到另一柱的最顶端,且在移动的过程中,永 远不允许出现大圆盘在小圆盘之上的情况。
探索数学中的递推和递归
探索数学中的递推和递归数学是一门充满魅力和无限可能的学科,其中递推和递归是数学中常见的重要概念。
递推和递归都是一种通过前一项或几项的信息来求解后一项的方法,但在使用和理解上存在一定的差异。
一、递推递推是一种按照特定规则从已知的初始值开始,通过逐步计算后一项的方式来得到数列或其他数学对象的方法。
在递推中,每一项都依赖于前一项或前几项的值。
我们可以通过一个具体的数列来理解递推的概念。
以斐波那契数列为例,斐波那契数列的递推公式为Fn = Fn-1 + Fn-2,其中F0 = 0,F1 = 1。
通过递推公式,我们可以从已知的F0和F1开始,不断计算得到后面的项,如F2=F1+F0=1+0=1,F3=F2+F1=1+1=2,以此类推。
递推在数学中的运用非常广泛。
它不仅可以用于数列,还可以应用于概率、几何等各个数学领域。
递推不仅简洁高效,而且能够提供一种清晰的计算思路,使得复杂的问题变得简单。
二、递归递归是一种通过调用自身来解决问题的方法。
递归的思想是将原始问题拆分成更小的相同问题,并通过递归调用来逐步解决这些小问题,最终得到原始问题的解。
递归的应用非常广泛,尤其在计算机科学中。
在计算机中,递归的应用可以极大地简化代码的编写和理解。
典型的例子是计算阶乘的递归函数。
以计算n的阶乘n!为例,递归的定义为n! = n * (n-1)!。
通过这个递归定义,我们可以将原始问题n的阶乘转化为更小的问题(n-1)的阶乘,再通过递归调用不断地将问题规模缩小,直到达到递归的基本情况,即当n=0或n=1时,阶乘的结果为1。
递归虽然功能强大,但也需要注意一些问题。
首先,递归函数的调用次数不能无限增长,否则会导致栈溢出等问题。
其次,递归函数的设计和调用需要合理,避免出现死循环或无限递归的情况。
总结:递推和递归都是数学中常见的求解方法,它们在解决问题时都能够提供一种清晰的思路,使得复杂的问题变得简单。
递推是一种按照特定规则从已知的初始值开始,通过逐步计算后一项的方式来得到数列或其他数学对象的方法。
C语言的递归算法解析
C语言的递归算法解析递归算法是一种经常在编程中使用的重要技术。
在C语言中,递归算法可以通过函数的自我调用来实现。
本文将对C语言中的递归算法进行详细解析,并介绍递归算法在实际应用中的一些常见场景。
一、什么是递归算法递归算法是一种通过函数的自我调用来解决问题的方法。
在递归算法中,一个函数可以直接或间接地调用自身。
递归算法通常分为两个部分:基本情况和递归情况。
基本情况是指能够直接解决的问题,而递归情况是指将问题划分为子问题并通过递归调用解决。
递归算法的核心思想是将原问题转化为规模更小的子问题,并通过递归调用解决子问题。
递归算法必须要有一个终止条件,否则会进入无限循环,导致程序崩溃或者运行时间过长。
二、递归算法的实现在C语言中,递归算法可以通过函数的自我调用来实现。
下面是一个求解斐波那契数列的递归算法示例:```c#include <stdio.h>int fibonacci(int n) {if (n == 0 || n == 1) {return n;} else {return fibonacci(n-1) + fibonacci(n-2);}}int main() {int n = 10;int result = fibonacci(n);printf("The %dth Fibonacci number is: %d\n", n, result);return 0;}```在上述代码中,`fibonacci`函数通过递归调用自身来求解斐波那契数列的第n个数。
如果n为0或者1,那么直接返回n,否则将问题划分为求解第n-1个数和第n-2个数的和,并通过递归调用来解决子问题。
三、递归算法的优缺点递归算法具有以下优点:1. 递归算法可以简化问题的解决过程,将大问题划分为小问题,降低了问题解决的复杂度。
2. 递归算法的逻辑清晰,代码简洁,易于理解和维护。
然而,递归算法也存在一些缺点:1. 递归算法需要占用大量的系统栈空间,函数的调用层级过深可能导致栈溢出的问题。
C语言递推与递归PPT课件
• void qsort(int array[], int start, int end) • 把数组下标为start到end的元素进行快速排序第18页/共25页快速排序问题5
7
3
8
1
4
2
6
2
7
3
8
1
4
5
6
2
5
3
8
1
4
7
6
2
4
3
8
1
5
7
6
2
4
3
5
1
8
7
6
2
4
3
1
5
8
7
6
1
4
3
2
第16页/共25页
汉诺塔问题
第17页/共25页
快速排序问题
• 快速排序思路如下
• 将要排序的数据放在数组array中 • 取a[0]变在变量m中,通过分区处理把m排在适当的位置,使
m左边的数都比m小,m右边的数都比m大 • 按照常上面的思路分别处理m左边和右边的数据 • 如果分区长度是1,停止处理
• 思路提示
• m个球取出来的n个,包含两种情况:n在其中和n不在其中
• 编程实现
• 使用递归思想 • 编写递归函数 int cmn(int m, int n)
第12页/共25页
计算组合数
第13页/共25页
汉诺塔问题
• 据说在古代印度bramah神庙中,有个和尚整天把3根 柱子上的金盘倒来倒去。初始在柱子A上有64个盘子串 在一起,每一个盘子都比它下面的盘子小,可以在ABC 三个柱子之间互相移动,最终要全部移动到柱子C上。 移动规则如下:每次只允许移动一个,且较大的盘子永 远不能放在较小的盘子上。
C语言技术中的递归算法实现方法
C语言技术中的递归算法实现方法递归是一种重要的算法思想,在C语言中可以通过递归来解决许多问题。
递归算法的核心思想是将一个大问题分解为若干个相同或相似的小问题,通过解决小问题来解决大问题。
本文将介绍C语言中递归算法的实现方法。
一、递归算法的基本原理递归算法的基本原理是函数调用自身。
在递归算法中,函数会不断地调用自身,直到满足某个条件才停止调用。
通过递归,可以将一个复杂的问题转化为一个或多个相同或相似的子问题,从而简化问题的解决过程。
二、递归算法的实现步骤1.确定递归函数的参数和返回值:在实现递归算法时,首先需要确定递归函数的参数和返回值。
参数是指传递给递归函数的数据,返回值是指递归函数的计算结果。
2.确定递归的终止条件:递归算法必须有一个终止条件,当满足该条件时,递归调用停止。
否则,递归将无限循环,导致程序崩溃。
3.确定递归的递推公式:递归算法通过递归的方式解决问题,需要确定递归的递推公式。
递推公式是指将一个大问题分解为一个或多个相同或相似的小问题的公式。
4.编写递归函数的代码:根据确定的参数、返回值、终止条件和递推公式,编写递归函数的代码。
递归函数的代码应该包括递推公式的实现和终止条件的判断。
三、递归算法的实例下面通过一个实例来介绍递归算法的具体实现方法。
假设我们要计算一个正整数n的阶乘,可以使用递归算法来解决。
```c#include <stdio.h>int factorial(int n) {// 终止条件if (n == 0 || n == 1) {return 1;}// 递推公式return n * factorial(n - 1);}int main() {int n;printf("请输入一个正整数:");scanf("%d", &n);printf("%d的阶乘为%d\n", n, factorial(n));return 0;}```在上述代码中,我们定义了一个名为factorial的递归函数,该函数用于计算一个正整数n的阶乘。
C语言递归函数的执行与求解
C语言递归函数的执行与求解C语言递归函数的执行与求解导语:函数的递归调用是在调用一个函数的执行过程中,直接或间接地调用该函数本身,使用递归函数的程序结构清晰,简单、易懂。
下面就由店铺为大家介绍一下C语言递归函数的执行与求解,欢迎大家阅读!1 递归函数C语言的特点之一就在于允许函数的递归调用,即允许在函数内部直接或间接的调用函数自身,被调用的函数被称为递归函数。
递归调用有直接递归调用和间接递归调用两种形式,递归函数常用于解决那些需要分多次求解且每次求解过程都基本类似的问题。
构造递归函数的关键在于寻找递归算法和终结条件。
递归算法就是解决问题所采取的方法和步骤,一般只要对问题的若干次求解过程进行分析和归纳,找出每一次求解过程之间的规律性,就可归纳出递归算法,终结条件是为了终结函数的递归调用而设置的一个条件或规则。
递归调用的一般形式为:函数类型函数名(参数列表){,,,,,函数名(参数列表)…..}2 递归条件使用递归调用编写程序时,要注意以下几点:(1)可以通过递归调用来缩小问题规模,且新问题与原问题有着相同的形式,只是所处理的对象具有一定的规律性。
也就是说解决问题的方法相同,调用函数的参数有规律的递增或递减。
(2)递归函数必须有一个终止处理条件,即必须有一个明确的结束条件,必须在适当的时候能够结束递归调用,否则会使程序陷入死循环,导致系统崩溃。
(3)有些使用递归算法求解的问题也可使用普通循环算法来实现,相较于循环程序,递归程序结构简单,逻辑清晰,但运行效率低,故在有其他算法可以代替的情况下,要尽量避免使用递归算法编写程序。
3 递归实例例:使用递归方法求n!。
在数学上n!=1×2×3×…×n-1×n,我们可以写成以下形式1 当n=0或n=1时n!=(n-1)!×n 当n>1时根据以上形式,可以写出如下递归调用程序:int f(n){if(n==1||n==0)return 1;elsereturn f(n-1)*n;}int main(){int n;scanf(“%d”,&n);if(n<0)printf(“data error!”);elseprintf(“%d”,f(n));return 0;}4 递归函数执行过程递归调用之所以能够实现,是因为函数在每一次执行过程中,都会把自己所有形参变量和局部变量复制一个副本,压入栈中,这些副本分别位于栈中不同的内存空间,和函数的其他执行过程毫不相干,这种机制使得递归调用成为可能。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
例6.4 定义一个函数check(n,d),让它返回一个布尔值。如果数字d在正整数n的 某位中出现则送回true,否则送回false。 例如:check(325719,3)==true;check(77829,1)==false;
例6.1 求:1!+2!+3!+„„+10!
#include<iostream> using namespace std; int main() { int sum=0; for (int i=1; i<=10; i++) sum+=js(i); cout<<"sum="<<sum<<endl; return 0; }
第六章 函数和递推递归算法
第一节 函数 第二节 递推算法 第三节 递归算法
前面我们曾经学习了程序设计中的三种基本控制结构(顺序、分 支、循环)。用它们可以组成任何程序。但在应用中,还经常用到子 程序结构。 通常,在程序设计中,我们会发现一些程序段在程序的不同地方 反复出现,此时可以将这些程序段作为相对独立的整体,用一个标识 符给它起一个名字,凡是程序中出现该程序段的地方,只要简单地写 上其标识符即可。这样的程序段,我们称之为子程序。 子程序的使用不仅缩短了程序,节省了内存空间及减少了程序的 编译时间,而且有利于结构化程序设计。因为一个复杂的问题总可将 其分解成若干个子问题来解决,如果子问题依然很复杂,还可以将它 继续分解,直到每个子问题都是一个具有独立任务的模块。这样编制 的程序结构清晰,逻辑关系明确,无论是编写、阅读、调试还是修改, 都会带来极大的好处。 在一个程序中可以只有主程序而没有子程序(本章以前都是如此), 但不能没有主程序,也就是说不能单独执行子程序。 在此之前,我们曾经介绍并使用了C++提供的各种标准函数,如 abs(),sqrt()等等,这些系统提供的函数为我们编写程序提供了很大 的方便。比如:求sin(1)+ sin(2)+...+sin(100)的值。但这些函 数只是常用的基本函数,编程时经常需要自定义一些函数。
在此例中,因为swap函数的参数为引用参数,所以,在函数swap中修 改a,b的值相当于在主函数main中修改c,d的值。
3.const形参 使用const修饰参数可避免在函数执行中修改参数。 举个例子:
void solve(const int &a) { a=1; } //该函数是错误的,因为a是 const形参,所以在函数体中不能被修改。
double area(double a,double b,double c) //此函数为 海伦-秦九韶公式 { double p=(a+b+c)/2; return sqrt(p*(p-a)*(p-b)*(p-c)); }
在函数说明中,如果形参的个数不止 一个,那么在程序中调用函数的实参个数 一定要与形参的个数一致,第一个实参对 应第一个形参,第二个实参对应第二个形 参...次序不能对调。
例6.3 任意输入10组三角形的三边,求其面积。 我们可以定义一个已知三角形三边求其面积的函数,设为area(a,b,c)。 程序如下:
#include<iostream> #include<cmath> using namespace std; double area(double,double,double); int main() { for (int i=1; i<=10; ++i) { double a,b,c; cout<<"input a,b,c"<<endl; cin>>a>>b>>c; if ((a+b<=c)||(a+c<=b)||(b+c<=a)) cout<<"data error!"<<endl; //判断三角形是否合法 else cout<<"s="<<area(a,b,c)<<endl; } return 0; }
使用const修饰参数也可使函数接受常量作为引用参数。 举个例子:
void fa(const int &a) { } void fb(int &a) { } int main() { fa(2); //正确,因为fa()使用了常量引用形参。 fb(2); //错误,因为fb()使用了非常量引用形参,不可以接受常量2。 }
1.函数的声明 调用函数之前先要声明函数原型。在主调函数中,或所有函数定义 之前,按如下形式声明: 类型说明符 被调函数名(含类型说明的形参表); 如果是在所有函数定义之前声明了函数原型,那么该函数原型在本 程序文件中任何地方都有效,也就是说在本程序文件中任何地方都可以 依照该原型调用相应的函数。如果是在某个主调函数内部声明了被调用 函数原型,那么该原型就只能在这个函数内部有效。 函数原型和函数定义在返回值类型、函数名和参数个数与类型必须 完全一致,否则,就会发生编译错误。下面对max()函数原型声明是合法 的。 int max(int x, int y); 也可以: int max(int , int ); 可以看到函数原型声明与函数定义时的第一行类似,只多了一个分 号,成为了一个声明语句而已。
现在的问题是:C++不提供js(x)这样一个标准函数,这个程序是 通不过的。如果是C++的标准函数,我们可以直接调用,如abs(x), sqrt(x)......而C++提供给我们的可供直接调用的标准函数不 多。没关系,我们编写自己的函数!
1.函数定义的语法形式
数据类型 函数名(形式参数表) { 函数体 //执行语句 } 关于函数的定义有如下说明: 函数的数据类型是函数的返回值类型(若数据类型为 void ,则无返回 值)。 函数名是标识符,一个程序中除了主函数名必须为main外,其余函数的 名字按照标识符的取名规则可以任意选取,最好取有助于记忆的名字。 形式参数(简称形参)表可以是空的(即无参函数);也可以有多个形 参,形参间用逗号隔开,不管有无参数,函数名后的圆括号都必须有。 形参必须有类型说明,形参可以是变量名、数组名或指针名,它的作 用是实现主调函数与被调函数之间的关系,通常将函数所处理的
编写一个阶乘的函数,我们给此函数取一个名字js。
int js(int n) { int s=1; for (int i=1; i<=n; ++i) s*=i; return s; }
在本例中,函数名叫js,只有一个int型的自变量n,函数js属 int型。在本函数中,要用到两个变量i,s。在函数体中,是一个求 阶乘的语句,n的阶乘的值在s中,最后由return语句将计算结果s值 带回,js()函数执行结束,在主函数中js()值就是s的值。 在这里,函数的参数n是一个接口参数,说得更明确点是入口参 数。如果我们调用函数:js(3),那么在程序里所有有n的地方,n被 替代成3来计算。在这里,3就被称为实参。又如:sqrt(4),ln(5), 这里4,5叫实参。而ln(x),sqrt(x)中的x,y叫形参。
数据、影响函数功能的因素或者函数处理的结果作为形参。在被调用 函数中的参数被称为形参。 函数中最外层一对花括号“{ }”括起来的若干个说明语句和执行语句 组成了一个函数的函数体。由函数体内的语句决定该函数功能。函数 体实际上是一个复合语句,它可以没有任何类型说明,而只有语句, 也可以两者都没有,即空函数。 函数不允许嵌套定义。在一个函数内定义另一个函数是非法的。但是 允许嵌套使用。 函数在没有被调用的时候是静止的,此时的形参只是一个符号,它标 志着在形参出现的位置应该有一个什么类型的数据。函数在被调用时 才执行,也就是在被调用时才由主调函数将实际参数(简称实参)值 赋予形参。这与数学中的函数概念相似,如数学函数: f(x)= x 2+x+1
1.非引用参数 普通的非引用类型的参数是通过复制对应的实参实现初始化。当 用参数副本初始化形参时,函数并没有访问调用所传递的实参本身, 因此不会修改实参的值。举个例子:
#include<iostream> using namespace std; void swap(int a,int b) { int tmp=a;a=b;b=tmp; } int main() { int c=1,d=2; swap(c,d); cout<<c<<' '<<d<<endl; return 0; } //程序输出为:1 2
例6.2 求1!+2!+„„+10!的值。 程序如下:
#include<iostream> using namespace std; nt js(int); int main() { int sum=0; for (int i=1; i<=10; ++i) sum+=js(i); cout<<"sum="<<sum<<endl; return 0; } int js(int n) { int s=1; for (int i=1; i<=n; ++i) s*=i; return s; }
这样的函数只有当自变量被赋值以后,才能计算出函数的值。
2.函数定义的例子 定义一个函数,返回两个数中的较大数。
int max(int x,int y) { return x>y?x:y; }
该函数返回值是整型,有两个整型的形参,用来接受实参传递的 两个数据,函数体内的语句是求两个数中的较大者并将其返回主调函 数。