实验8 函数——递归函数

合集下载

函数递归实验报告

函数递归实验报告

一、实验目的1. 理解递归函数的概念和基本原理;2. 掌握递归函数的设计方法;3. 通过实验加深对递归函数在实际问题中的应用理解。

二、实验环境1. 操作系统:Windows 10;2. 编程语言:C语言;3. 开发环境:Visual Studio 2019。

三、实验内容1. 设计一个递归函数,计算斐波那契数列的第n项;2. 设计一个递归函数,判断一个整数是否为素数;3. 设计一个递归函数,计算n的阶乘;4. 分析递归函数的性能,并讨论递归算法的优缺点。

四、实验步骤1. 设计斐波那契数列的递归函数斐波那契数列的定义如下:F(1) = 1, F(2) = 1F(n) = F(n-1) + F(n-2) (n > 2)下面是斐波那契数列的递归函数实现:```cint fibonacci(int n) {if (n <= 0) {return 0;} else if (n == 1 || n == 2) {return 1;} else {return fibonacci(n - 1) + fibonacci(n - 2); }}```2. 设计素数的递归函数判断一个整数是否为素数的递归函数实现如下:```cint is_prime(int n) {if (n <= 1) {return 0;} else if (n == 2) {return 1;} else {return is_prime(n - 1) && n % (n - 1) != 0; }}```3. 设计阶乘的递归函数计算n的阶乘的递归函数实现如下:```cint factorial(int n) {if (n <= 1) {return 1;} else {return n factorial(n - 1);}}```4. 分析递归函数的性能递归函数的性能分析如下:(1)斐波那契数列的递归函数存在大量重复计算,时间复杂度为O(2^n),效率较低;(2)素数的递归函数也存在重复计算,时间复杂度为O(n),相对较高;(3)阶乘的递归函数同样存在重复计算,时间复杂度为O(n),相对较高。

什么是递归函数

什么是递归函数

1.什么是递归函数(recursive function)递归函数即自调用函数,在函数体内部直接或间接地自己调用自己,即函数的嵌套调用是函数本身。

例如,下面的程序为求n!:long fact(int n){if(n==1)return1;return fact(n-1)*n;//出现函数自调用}2.函数调用机制的说明任何函数之间不能嵌套定义,调用函数与被调用函数之间相互独立(彼此可以调用)。

发生函数调用时,被调函数中保护了调用函数的运行环境和返回地址,使得调用函数的状态可以在被调函数运行返回后完全恢复,而且该状态与被调函数无关。

被调函数运行的代码虽是同一个函数的代码体,但由于调用点,调用时状态,返回点的不同,可以看作是函数的一个副本,与调用函数的代码无关,所以函数的代码是独立的。

被调函数运行的栈空间独立于调用函数的栈空间,所以与调用函数之间的数据也是无关的。

函数之间靠参数传递和返回值来联系,函数看作为黑盒。

这种机制决定了C/C++允许函数递归调用。

3.递归调用的形式递归调用有直接递归调用和间接递归调用两种形式。

直接递归即在函数中出现调用函数本身。

例如,下面的代码求斐波那契数列第n项。

斐波那契数列的第一和第二项是1,后面每一项是前二项之和,即1,1,2,3,5,8,13,...。

代码中采用直接递归调用:long fib(int x){if(x>2)return(fib(x-1)+fib(x-2));//直接递归elsereturn1;}间接递归调用是指函数中调用了其他函数,而该其他函数却又调用了本函数。

例如,下面的代码定义两个函数,它们构成了间接递归调用:int fnl(int a){int b;b=fn2(a+1);//间接递归//...}int fn2(int s){int c;c=fnl(s-1); //间接递归//...}上例中,fn1()函数调用了fn2()函数,而fn2()函数又调用了fn1()函数。

实验一递归函数的设计与实现

实验一递归函数的设计与实现

实验一递归函数的设计与实现递归函数是一种函数调用自身的方式,它经常在编程中使用来解决那些可以分解为相同类型的子问题的问题。

递归函数的设计与实现需要仔细考虑问题的结构以及递归的边界条件和递归关系,同时也要注意效率和性能。

在本文中,我将介绍递归函数的设计和实现的一般原则,并通过一个具体的例子来说明。

递归函数的设计步骤如下:1.确定问题的基本情况:递归函数应该首先确定问题的基本情况,即递归的边界条件。

这是递归函数的停止条件,用于终止函数的递归调用。

在确定基本情况时,需要考虑问题的规模和特殊情况。

2.定义递归关系:递归函数的核心部分是定义递归关系,即将原始问题分解为相同类型的子问题。

递归关系应该满足问题的结构,即递归应该通过解决更小规模的问题来解决原始问题。

3.编写递归函数:在确定了基本情况和递归关系后,可以开始编写递归函数。

递归函数应该根据基本情况判断是否终止递归,如果不终止,则需要调用自身来解决更小规模的问题,并根据递归关系将结果组合成原始问题的解。

递归函数的实现需要考虑以下几点:1.参数传递:递归函数应该正确传递参数,以便在每次递归调用中获得所需的参数。

参数的传递应该根据问题的结构和递归关系设计。

2.局部变量:递归函数中使用的局部变量应该正确声明和初始化,以确保在每次递归调用中的正确性。

3.返回值:递归函数应该正确定义和返回结果,以使得在递归过程中的每一步都能获得正确的结果,并组合成原始问题的解。

下面是一个具体的例子来说明递归函数的设计和实现。

问题描述:计算斐波那契数列的第n个数。

斐波那契数列是一个递归数列,定义如下:F(0)=0F(1)=1F(n)=F(n-1)+F(n-2)(n>=2)基本情况:当n等于0或1时,斐波那契数列的第n个数为n本身。

递归关系:斐波那契数列的第n个数等于第n-1个数与第n-2个数的和。

递归函数的实现:```def fibonacci(n):if n == 0:return 0elif n == 1:return 1else:return fibonacci(n-1) + fibonacci(n-2)```在这个例子中,递归函数`fibonacci`通过判断基本情况来终止递归。

递归函数——精选推荐

递归函数——精选推荐

递归函数如果⼀个函数在内部调⽤⾃⾝,这个函数就叫做递归函数递归函数的简单定义如下:def recursion():return recursion()这只是⼀个简单的定义,什么也做不了。

当然,你可以尝试会发⽣什么结果,理论上会永远运⾏下去,但实际操作时发现不⼀会⼉程序就报错了,因为每次调⽤函数都会⽤掉⼀点内存,在⾜够多的函数调⽤发⽣后,空间⼏乎被占满,程序就会报错。

RecursionError: maximum recursion depth exceeded#超过最⼤递归深度这类递归被称为⽆穷递归(infinite recursion),理论上永远都不会结束,当然,我们需要能实际做事情的函数,有⽤的递归函数应该满⾜如下条件:(1)当函数直接返回值时有基本实例(最⼩可能性问题)(2)递归实例,包括⼀个或多个问题最⼩部分的递归调⽤使⽤递归的关键在于将问题分解为⼩部分,递归不能永远进⾏下去,因为它总是以最⼩可能性问题结束,⽽这些问题⼜存储在基本实例中。

函数调⽤⾃⾝怎么实现呢??其实函数每次被调⽤时都会创建⼀个新的命名空间,也就是当函数调⽤‘⾃⼰’时,实际上运⾏的是两个不同的函数(也可以说⼀个函数具有两个函数的命名空间)。

我们来看⼀个递归⽰例,计算阶乘n!=1*2*3*4*5*……*n,⽤函数fact(n)表⽰,可以看出:fact(n)=1*2*3*……*(n-1)*n=(n-1)!*n=fact(n-1)*n所以,fact(n)可以表⽰为n*fact(n-1),只有n=1时需要特殊处理于是,fact(n)⽤递归⽅式定义函数如下:def fact(n):if n==1:return 1return n*fact(n-1)执⾏该函数:>>> fact(1)1>>> fact(5)120>>> fact(100) 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000L 如果我们计算fact(5),可以根据函数定义看到计算过程如下:===> fact(5)===> 5 * fact(4)===> 5 * (4 * fact(3))===> 5 * (4 * (3 * fact(2)))===> 5 * (4 * (3 * (2 * fact(1))))===> 5 * (4 * (3 * (2 * 1)))===> 5 * (4 * (3 * 2))===> 5 * (4 * 6)===> 5 * 24===> 120由函数定义可知,递归函数的有点是定义简单,逻辑清晰。

递归实验报告

递归实验报告

递归实验报告递归实验报告引言递归是计算机科学中一种重要的概念,它在问题解决和算法设计中起到了关键的作用。

本文将对递归进行实验探究,通过编写一些递归函数来解决不同类型的问题,并对其性能和应用进行评估。

一、递归的基本原理递归是一种通过调用自身来解决问题的方法。

它包含两个重要的要素:基本情况和递归情况。

基本情况是指问题可以直接解决的情况,而递归情况则是指问题需要通过调用自身来解决的情况。

在递归函数中,我们需要确保递归情况能够最终达到基本情况,否则会出现无限递归的情况。

二、递归的应用1. 阶乘计算阶乘是一个常见的递归应用。

我们可以定义一个递归函数来计算一个正整数的阶乘。

例如,计算5的阶乘可以通过调用函数fact(5)来实现。

在函数内部,我们将问题转化为计算4的阶乘,并不断递归下去,直到问题达到基本情况,即计算1的阶乘为止。

2. 斐波那契数列斐波那契数列也是递归的一个经典应用。

该数列的定义是:第一个和第二个数为1,从第三个数开始,每个数都是前两个数之和。

我们可以编写一个递归函数来计算斐波那契数列中的第n个数。

在函数内部,我们将问题转化为计算第n-1个数和第n-2个数的和,并不断递归下去,直到问题达到基本情况,即计算第一个或第二个数为止。

三、递归的性能评估递归在解决某些问题时可以提供简洁的解决方案,但也可能带来性能上的问题。

递归函数的调用涉及到函数的压栈和弹栈操作,这会增加程序的开销。

在处理大规模问题时,递归可能导致栈溢出的问题。

因此,在使用递归时,我们需要仔细评估其性能,确保其适用于当前的问题规模。

四、递归的优化技巧为了提高递归函数的性能,我们可以采用一些优化技巧。

其中一种常见的优化方法是尾递归优化。

尾递归是指递归函数在递归调用时,只返回递归函数本身的结果,而不进行其他的计算。

这样可以减少函数调用的开销,提高程序的执行效率。

五、结论递归是一种强大的问题解决方法,它在计算机科学中有着广泛的应用。

通过实验我们可以发现,递归函数可以提供简洁的解决方案,但在处理大规模问题时需要注意其性能问题。

python 函数递归函数

python 函数递归函数

python 函数递归函数(实用版)目录1.递归函数的定义与特点2.Python 中的递归函数3.递归函数的应用实例4.递归函数的注意事项正文1.递归函数的定义与特点递归函数是一种在函数体内部调用自身的函数。

它的主要特点是在执行过程中,函数会不断地将自己调用,直到满足某个特定条件(通常是基本情况),然后从最后一个调用开始,依次返回结果,最终得到整个函数的输出。

递归函数通常用于解决具有重复子问题的复杂问题。

2.Python 中的递归函数在 Python 中,定义一个递归函数非常简单。

只需在函数体内部调用该函数即可。

需要注意的是,递归函数必须有一个基本情况(也称为递归出口),即在某个特定条件下,函数不再调用自身,而是返回一个值。

3.递归函数的应用实例以下是一个使用递归函数计算阶乘的实例:```pythondef factorial(n):if n == 0 or n == 1:return 1else:return n * factorial(n-1)print(factorial(5)) # 输出 120```在这个例子中,`factorial`函数计算一个正整数`n`的阶乘。

当`n`等于 0 或 1 时,函数返回 1(基本情况)。

对于其他情况,函数计算`n`乘以`factorial(n-1)`的结果,从而实现递归调用。

4.递归函数的注意事项虽然递归函数可以解决许多有趣的问题,但使用时需要注意以下几点:- 确保递归函数有一个基本情况,以便在满足条件时停止递归调用。

- 递归函数的调用应该有明确的终止条件,否则可能导致无限递归,最终导致程序崩溃。

- 递归函数在每次调用时都会占用一定的栈空间,因此需要注意递归深度,避免栈溢出。

递归函数是一种强大的工具,用于解决具有重复子问题的复杂问题。

在 Python 中,定义和调用递归函数非常简单。

实验8函数的调用与递归

实验8函数的调用与递归

实验8 函数的调用与递归一、实验目的1. 熟练掌握函数的定义、函数的调用的基本格式与方法。

2. 理解递归函数的基本概念和计算机执行递归函数的过程。

3. 初步认识结构化程序设计。

二、实验要求1. 通过一个完整的程序,学习函数的定义与调用的基本格式与方法。

2. 通过程序中return语句的使用,理解函数返回值的概念,并学习如何取得函数返回值。

3. 通过编写含有参数的函数,进一步理解函数间的参数传递过程。

4. 通过一个含有递归函数的实例,理解递归函数的基本概念,学习分析计算机执行递归函数的过程。

5. 通过一个比较复杂的程序,初步认识结构化程序设计实例。

三、实验内容1. 调试运行下列程序,并注意函数的定义格式以及函数的调用方法,特别要注意形参变量与实参变量的对应关系和形参与实参之间的数据传递。

float sum_of_square ( int n ){int i;float sum=0.0;for (i=1; i<=n; i++)sum=sum+i*i;return(sum);}main ( ){float s;s=sum_of_square(12)* sum_of_square(15);printf (“s=%f”,s);}2. 调试运行下列程序,并注意函数间的参数传递,深刻理解“单向传递(值的传递)”。

(1) main ( ){int a[3]={1,2,3};void f1( );f1(a[0],a[1],a[2] );printf (“a[0]=%d,a[1]=%d,a[2]=%d\n”, a[0],a[1],a[2] );}void f1(int x,int y,int z ){x++;y=y+2;z=z+3;printf (“x=%d,y=%d,z=%d\n”, x,y,z );return;}(2) main ( ){int a[3]={1,2,3};void f2( );f2(a);printf (“a[0]=%d,a[1]=%d,a[2]=%d\n”, a[0],a[1],a[2] );}void f1(int x[] ){x[0]++;x[1]=x[1]+2;x[2]=x[2]+3;printf (“x[0]=%d,x[1]=%d,x[2]=%d\n”, x[0],x[1],zx[2]);return;}3. 编写一个递归函数,计算整数a 和b的最大公因子,并分析程序运行时函数调用情况。

递归函数名词解释

递归函数名词解释

递归函数名词解释
递归函数是指在一个函数的定义中又调用了该函数本身的情况。

递归函数在程序设计中起着非常重要的作用,能够简化程序的结构,提高代码的可读性和可维护性。

递归函数通常用于解决问题的分而治之,将一个大问题分解成几个小问题,通过递归调用来解决这些小问题,最终达到解决整个大问题的目的。

在递归函数中,需要定义一个基本情况,也就是递归的结束条件,否则函数会陷入无限循环,无法正常结束。

当函数遇到基本情况时,递归调用将停止,函数返回结果。

递归函数的基本情况可以看作是递归的出口,也是问题被解决的最小单元。

递归函数可以直接或间接地调用自身,直接递归是指函数在自身的定义中直接调用自身,间接递归是指函数在调用其他函数的过程中间接地调用自身。

无论是直接递归还是间接递归,都需要小心处理递归调用的次数,以免造成栈溢出或者程序性能下降的问题。

递归函数在编程中有许多应用,比如在树的数据结构中,可以使用递归函数来遍历树的节点;在计算数学问题中,如斐波那契数列等,也可以使用递归函数来解决;在图形学中,递归函数可以用来绘制分形图形等。

总的来说,递归函数是一种非常有用的编程技巧,能够简化程序的结构,提高代码的可读性和可维护性。

但是在使用递归函数时需要小心处理递归调用的次数,避免陷入无限循环的情况。

递归函数的正确使用将会极大地丰富程序设计的思路和方法,提高程序的效率和可扩展性。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

淮海工学院计算机科学系实验报告书
课程名:《C语言程序设计A 》
题目:实验8 函数
——递归函数
班级:软嵌151
学号:**********
*名:***
1、实验内容或题目
(1)用递归编写n!的函数,并在main主函数中调用此函数。

(2)有n个大小不同的盘片从大到小放在A柱上,另有B和C两个空柱,要求将这n个盘片从A柱搬到C柱上,在搬动过程中,每次只能搬一个盘片,而且小的不能放在大的之下。

编写hanio函数实现搬迁过程。

(3)编写一个程序,求解皇后问题:在n×n的方格棋盘上,放置n个皇后,要求每个皇后不同行、不同列、不同左右对角线。

2、实验目的与要求
(1)要求熟练掌握函数的定义和调用,熟悉函数返回值的使用。

(2)熟悉函数调用的方式和过程。

(3)重点掌握递归函数的使用。

(4)要求实验的第2题采用递归函数编写,盘片的数目在main主函数中输入。

提示:函数的参数定义如hanio(n,A,C,B),表示将n个盘片从A柱通过C柱搬到B柱。

(5)要求实验的第3题采用递归函数编写皇后的个数n由用户输入,其值不能超过20;采用整数数组q[N]求解结果,因为每列只能放一个皇后,q[i]的值表示第i个皇后所在的行号,即该皇后放在(q[i],i)的位置上。

求解皇后问题的递归模型如下:place(i,n):若i=n,则n个皇后放置完毕,输出解(输出q数组元素)
place(k,n):在第k列找一个合适位置i,放置一个皇后(即q[k]=i);place(k+1,n);其中,place(k,n)表示前面的第1,…,k-1个皇后放置好后,现在用于放置k,…,n的皇后。

3、实验步骤与源程序
⑴实验步骤
⑵源代码
(1)、
#include<stdio.h>
long fac(int n)
{
long f;
if(n==0||n==1)
f=1;
else
f=n*fac(n-1);
return (f);
}
void main()
{
int n;
printf("请输入一个整数n:");
scanf("%d",&n);
printf("%d!=%d\n",n,fac(n));
}
(2)、
#include<stdio.h>
int main()
{
void hanio(int n,char A,char C,char B);
int m;
printf("请输入盘片的数量:");
scanf("%d",&m);
printf("移动%d个盘片的步骤如下:\n",m);
hanio(m,'A','B','C');
return 0;
}
void hanio(int n,char one, char two, char three) {
void move(char x,char y);
if(n==1)
move(one,three);
else
{
hanio(n-1,one,three,two);
move(one,three);
hanio(n-1,two,one,three);
}
}
void move(char x,char y)
{
printf("%c-->%c\n",x,y);
}
(3)、
#include <stdio.h>
#include <stdlib.h>
const int N=20;
int q[N];
int cont=1;
void print(int n)
{
int i;
printf("第%2d个解:",cont);
for (i=1;i<=n;i++)
printf("%d ",q[i]);
cont++;
printf("\n");
}
int find(int i,int k)
{
int j;
j=1;
while (j<k)
{
if ((q[j]==i) || (abs(q[j]-i)==abs(j-k)))
return 0;
j++;
}
return 1;
}
void place(int k,int n)
{
if (k>n)
print(n);
else
for (int i=1;i<=n;i++)
if (find(i,k))
{
q[k]=i;place(k+1,n);
}
}
int main()
{
int n;
int result;
printf("皇后问题(n<20)\n");
printf("输入摆放的皇后个数:\n n=");
scanf("%d",&n);
if (n>20)
{
printf("n值太大,不能求解\n");
result=1;
}
else if(n>0&&n<4)
{
printf("不存在皇后问题!");
printf("\n");
result=0;
}
else
{
printf("有%d个皇后问题求解如下:\n",n);
place(1,n);
printf("\n");
result=1;
}
return result;
}
4、测试数据与实验结果(可以抓图粘贴)(1)、
(2)、
(3)、
5、结果分析与实验体会
(1)、在调用一个函数的过程中又出现或间接地调用函数本身,称为函数的递归调用。

(2)、必须与函数的嵌套调用区分开。

(3)、如果要求递归过程不是无限制进行下去,必须具有一个结束递归过程的条件!。

相关文档
最新文档