递归算法在C,C++中的实现与描述docx

合集下载

先序遍历的递归算法c语言

先序遍历的递归算法c语言

先序遍历的递归算法c语言先序遍历是二叉树遍历的一种方法,它的遍历顺序是先访问根结点,然后递归地先序遍历左子树,最后递归地先序遍历右子树。

在C语言中,我们可以通过递归算法来实现二叉树的先序遍历。

首先,我们需要定义二叉树的结构体,包括树的节点结构以及创建树的函数。

树的节点结构体定义如下:```ctypedef struct TreeNode {int data;struct TreeNode* left;struct TreeNode* right;} TreeNode;```接下来,我们可以编写递归函数来实现先序遍历。

先序遍历的递归算法如下:```cvoid preorderTraversal(TreeNode* root) {if (root == NULL) {return;}printf("%d ", root->data); // 访问根结点preorderTraversal(root->left); // 递归遍历左子树preorderTraversal(root->right); // 递归遍历右子树}```在这段代码中,我们首先判断根结点是否为空,如果为空则直接返回。

然后,我们先访问根结点的数据,然后递归地对左子树和右子树进行先序遍历。

接下来,我们可以编写一个测试函数来创建二叉树并进行先序遍历:```cint main() {// 创建二叉树TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));root->data = 1;root->left = (TreeNode*)malloc(sizeof(TreeNode));root->left->data = 2;root->left->left = NULL;root->left->right = NULL;root->right = (TreeNode*)malloc(sizeof(TreeNode));root->right->data = 3;root->right->left = NULL;root->right->right = NULL;// 先序遍历二叉树printf("Preorder traversal: ");preorderTraversal(root);return 0;}```在这个测试函数中,我们首先创建了一个简单的二叉树,然后调用先序遍历函数对这棵树进行遍历,并输出遍历结果。

c语言递归算法实验报告,递归算法的设计与实现实验报告-read.doc

c语言递归算法实验报告,递归算法的设计与实现实验报告-read.doc

c语⾔递归算法实验报告,递归算法的设计与实现实验报告-read.doc递归算法的设计与实现实验报告-read递归算法的设计与实现实验报告⼀、实验⽬的:a)掌握递归算法的基本思想及其与数学归纳法的关系;b)掌握递归算法设计与实现。

⼆、实验内容a)⽤递归算法计算n!;b)⽤递归⽅法求⾮负整数a和b(a,b不全为0)的最⼤公约数。

三、实验要求a)⽤伪代码计算n!和求⾮负整数a,b(a,b不全为零)的最⼤公约数的递归算法;b)⽤C++语⾔实现算法并测试通过;c)⽐较采⽤欧⽒算法和递归算法求⾮负a,b(a,b不全为零)的最⼤公约数的执⾏效率。

四、(⼀)使⽤递归算法求n!的伪代码表⽰:1.Procedurefactorial (n)2. if n= = 0 then3. return (1)4. return (n * factorial (n-1))5. end(⼆)使⽤递归算法求⾮负整数a和b(a,b不全为0)的最⼤公约数的伪代码表⽰:输⼊:a和b(不全为0的⾮负整数)输出:a和b的最⼤公约数1. Procedure gcd_recurs (a, b)2. if a3. swap (a, b)4. if b = 0 then5. return (a)6. a 除以 b 得到 a = bq + r ,0 £ r < b7. redurn (gcd_recurs (b, r))8. end gcd_recurs五、(⼀)使⽤递归算法求n!的C语⾔实现:#include"stdio.h"long fac(int n){long result;if(n==0||n==1)result=1;elseresult=n*fac(n-1);return result;}main(){int x;long f;printf("please input one numbers: ");scanf("%d",&x);if(x<=0)printf("ERROR!\n");else{f=fac(x);printf("%d!=%ld\n",x,f);}}结果截图:(⼆)使⽤递归算法求⾮负整数a和b(a,b不全为0)的最⼤公约数的C语⾔实现:#include"stdio.h"int gcd(int a,int b){int temp,c;if(a{temp=a;a=b;b=temp;}if(b==0)return a;else{c=a%b;return(gcd(b,c));}}main(){int a,b;printf("please input two numbers:\n");scanf("%d%d",&a,&b);printf("gcd(%d,%d)=%d\n",a,b,gcd(a,b));}结果截图:六、⽐较采⽤欧⽒算法和递归算法求⾮负a,b(a,b不全为零)的最⼤公约数的执⾏效率。

全排列递归算法c语言

全排列递归算法c语言

全排列递归算法c语言
全排列是一种将一组元素进行排列得到所有可能的组合的算法。

递归是一种重复调用函数本身的方法,可以用来实现全排列算法。

以下是一个使用递归算法实现全排列的C语言代码示例:// 交换数组中两个元素的位置
// 递归生成全排列
// 将第i个元素与第start个元素交换位置 // 递归生成剩余元素的全排列
// 恢复数组的原始顺序
这段代码使用了递归的方式生成数组 `arr` 的全排列。

`permute` 函数接受一个数组、起始位置 `start` 和结束位置`end` 作为参数。

在每一次递归调用中,它将当前位置的元素与后续位置的元素依次交换,并递归生成剩余元素的全排列。

当`start` 等于 `end` 时,表示已经完成了一种排列,将其打印出来。

运行上述代码,将会输出以下结果:
1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
3 1 2
```
这些结果是给定数组 `[1, 2, 3]` 的所有全排列。

c语言递归求和

c语言递归求和

c语言递归求和(原创版)目录1.递归求和的概述2.C 语言中递归求和的实现方法3.递归求和的注意事项正文【1.递归求和的概述】递归求和是计算机编程中常见的一种算法,用于计算一个数列中所有数字的和。

在 C 语言中,递归求和可以通过调用同一个函数来实现。

递归求和的优点是可以处理任意数量的数字,但缺点是效率较低,因为存在大量的重复计算。

【2.C 语言中递归求和的实现方法】在 C 语言中,递归求和的实现方法如下:```c#include <stdio.h>int sum(int n) {if (n == 1) {return 1;} else {return n + sum(n-1);}}int main() {int n;printf("请输入数字个数:");scanf("%d", &n);int sum_n = sum(n);printf("%d", sum_n);return 0;}```在这个例子中,我们定义了一个名为`sum`的函数,用于计算数字和。

当输入的数字`n`为 1 时,返回 1;否则,返回`n`加上`sum(n-1)`的结果。

在`main`函数中,我们通过`scanf`函数读取用户输入的数字个数,然后调用`sum`函数计算数字和,并输出结果。

【3.递归求和的注意事项】在使用递归求和时,需要注意以下几点:- 递归求和的效率较低,因为存在大量的重复计算。

如果数字个数较大,可能会导致程序运行时间过长。

- 递归求和只适用于计算数字和,不能用于其他计算。

如果需要进行其他计算,需要重新编写代码。

- 在使用递归求和时,需要注意递归条件的设置。

如果递归条件设置不当,可能会导致程序无法正常运行。

递归求和是一种常用的算法,可以用于计算数字和。

递归算法实验报告doc

递归算法实验报告doc

递归算法实验报告篇一:递归算法的设计和实现的实验报告班级学号姓名实验组别试验日期室温报告日期成绩报告内容:(目的和要求、原理、步骤、数据、计算、小结等)实验名称:递归算法的设计和应用实验目的:1. 掌握递归算法的实现。

2. 实现递归算法的应用。

实验环境(硬/软件要求):Windows XX, Visual C++ 6.0实验内容:用递归算法实现前n个自然数的累加和与平均数【C语言源程序】#includeint Digui(int n)//设计递归算法功能为求前n个整数的和//{if(n==0)return 0;if(n==1)return 1;else return Digui(n-1)+n;}int main(){int n;printf("请输入n的值:\n");scanf("%d",&n);printf("计算结果为:\n%d\n",Digui(n));printf("这n个数的平均数是:\n%f\n",(float)Digui(n)/n);}篇二:数据结构- 递归算法实验报告实验报告实验五递归算法实验目的:1.熟悉递归算法的实现过程及实现机理;2.熟练并掌握递归算法的设计方法;3.了解递归算法到非递归算法的转换。

实验原理:高级程序语言函数调用原理;递归算法的设计方法。

实验内容:6-14 折半查找问题。

折半查找问题的描述见6.1节,折半查找问题的递归算法见例6-2。

要求:(1)设计折半查找问题的循环结构算法;(2)设计一个查找成功的例子和一个查找不成功的例子,并设计测试主程序;(3)设计一个包含10000个数据元素的查找成功的例子,然后分别调用循环结构的查找算法和递归结构的查找算法,并测试出两种算法在计算机上的实际运行时间。

实验结果:(1)折半查找问题的循环结构算法程序为:int Csearch(int test[],int x,int low,int high) {int i;for( i=0;i {if(x==test[i]) return i;else if(x>test[i])low=i+1;else high=i-1;}if(i>=high) return -1;}(2)①查找成功的例子:#includeint Csearch(int test[],int x,int low,int high) {int i;for( i=0;i {if(x==test[i]) return i;else if(x>test[i])low=i+1;else high=i-1;}if(i>=high) return -1;}int main(){int a[10]={1,2,3,4,5,6,7,8,9,10};int x=6,flag ;int low=0,high=10;flag=Csearch(a,x,0,10);if(flag==-1) printf("searching is failed!\n"); else printf("searching is success!\n") ;printf("This program is made by 10273206\n"); }运行结果为:②查找失败的例子为:#includeint Csearch(int test[],int x,int low,int high) {int i;for( i=0;i {if(x==test[i]) return i;else if(x>test[i])low=i+1;else high=i-1;}if(i>=high) return -1;}int main(){int a[10]={1,2,3,4,5,6,7,8,9,10};int x=11,flag ;int low=0,high=10;flag=Csearch(a,x,0,10);if(flag==-1) printf("searching is failed!\n"); else printf("searching is success!\n") ;printf("This program is made by 10273206\n"); }运行结果为:(3)程序为:#include#includeint Bsearch(int a[],int x,int low,int high) {int mid;if(low>high) return -1;mid=(low+high)/2;if(x==a[mid]) return mid;else if(x Bsearch(a,x,low,mid-1);elseBsearch(a,x,mid+1,high);}int Csearch(int test[],int x,int low,int high) {int i;for( i=0;i {if(x==test[i]) return i;else if(x>test[i])low=i+1;else high=i-1;}if(i>=high) return -1;}int main(){time_t start,end;double dif;int Bsearch(int a[],int x,int low,int high);int Csearch(int test[],int x,int low,int high);int a[10000],x,y,i,bn,flag;int low=0,high=10000,mid=0;printf("please enter number:\n");scanf("%ld",&x);for( i=0;i a[i]=i+1;time(&start);bn=Bsearch(a,x,0,10000);if(bn==-1) printf("%d is not in a !\n",x);else printf("%d is in a,suffix is %d\n",x,bn);time(&end);dif=difftime(end,start);printf("di gui method use time is:%f seconds\n",dif);time(&start);flag=Csearch(a,x,0,10000);if(flag==-1) printf("%ld is not in a !\n",x);else printf("%d is in a,suffix is %d\n",x,flag);time(&end);dif=difftime(end,start);printf("xun huan method use time is :%f seconds\n",dif);printf("This program is made by 10273206\n");}运行结果为:总结与思考通过实验我初步了解了递归算法到非递归算法的转换,递归算法在数据结构存储中用处很大。

递归算法在C语言项目实践中的应用

递归算法在C语言项目实践中的应用

递归算法在C语言项目实践中的应用摘要算法设计是计算机编程的核心,也是实施C语言项目实践的关键,算法的优劣及效率的高低决定了项目的性能和优劣。

递归算法作为一种特殊的算法,其设计理念简洁而巧妙,其强大的自我调用能力,使得递归算法在进行项目实践和应用程序开发中得到广泛应用。

本文通过C语言中常见的项目实践问题的分析求解,旨在理解递归算法的内部机制,探索递归算法的应用方法和技巧。

【关键词】递归算法C语言项目实践递归是计算机编程中一个非常重要的设计思想,在程序设计语言中广泛应用。

它是调用一个函数的过程中又出现直接或者间接地调用该函数本身。

这种算法十分另类却又非常有效,广泛应用于各种程序设计中,采用递归编写程序可以使程序变得简洁和清洗。

1 递归思想递归算法是C语言中经常使用的一种将复杂问题简单化的方法,其基本思想是通过递归调用,将原始比较复杂的大规模问题按照一定的要求进行分解,形成若干小问题,而这些小问题的求解方式和方法跟该问题的方式和方法相同,然后递归调用该子函数来表示问题的解。

具体来说就是自身调用自身,通过若干步重复的简单运算来描述复杂问题。

C语言中常常会遇到在调用一个函数时又要直接或间接调用该函数本身的情况,这就是函数的递归调用,该函数被称为递归函数。

递归调用是C语言的特点之一,C语言程序除了主函数之外均能够进行递归调用。

函数在递归调用的过程中,调用函数又是被调用函数。

递归函数执行时将会不断的调用自身。

递归每调用一次就进入新的一层继续执行调用程序,如此反复地执行。

递归算法使程序设计更加简洁明了以代替循环语句使用,且其使用效果比循环语句使用效果更好。

然而,对于递归算法的应用存在两方面需要注意的问题。

一是递归算法中的参数设置和参数传递问题,包括形参和实参的对应关系,参数传递中的值传递和地址传递等,这是函数调用中普遍存在的问题;二是递归调用的终止方式,递归函数的设计一定要避免无休止的反复调用其自身,否则容易进入死循环,出现意想不到的问题。

递归算法实验报告doc

递归算法实验报告doc

递归算法实验报告篇一:递归算法的设计和实现的实验报告班级学号姓名实验组别试验日期室温报告日期成绩报告内容:(目的和要求、原理、步骤、数据、计算、小结等)实验名称:递归算法的设计和应用实验目的:1. 掌握递归算法的实现。

2. 实现递归算法的应用。

实验环境(硬/软件要求):Windows XX, Visual C++ 6.0实验内容:用递归算法实现前n个自然数的累加和与平均数【C语言源程序】#includeint Digui(int n)//设计递归算法功能为求前n个整数的和//{if(n==0)return 0;if(n==1)return 1;else return Digui(n-1)+n;}int main(){int n;printf("请输入n的值:\n");scanf("%d",&n);printf("计算结果为:\n%d\n",Digui(n));printf("这n个数的平均数是:\n%f\n",(float)Digui(n)/n);}篇二:数据结构- 递归算法实验报告实验报告实验五递归算法实验目的:1.熟悉递归算法的实现过程及实现机理;2.熟练并掌握递归算法的设计方法;3.了解递归算法到非递归算法的转换。

实验原理:高级程序语言函数调用原理;递归算法的设计方法。

实验内容:6-14 折半查找问题。

折半查找问题的描述见6.1节,折半查找问题的递归算法见例6-2。

要求:(1)设计折半查找问题的循环结构算法;(2)设计一个查找成功的例子和一个查找不成功的例子,并设计测试主程序;(3)设计一个包含10000个数据元素的查找成功的例子,然后分别调用循环结构的查找算法和递归结构的查找算法,并测试出两种算法在计算机上的实际运行时间。

实验结果:(1)折半查找问题的循环结构算法程序为:int Csearch(int test[],int x,int low,int high) {int i;for( i=0;i {if(x==test[i]) return i;else if(x>test[i])low=i+1;else high=i-1;}if(i>=high) return -1;}(2)①查找成功的例子:#includeint Csearch(int test[],int x,int low,int high) {int i;for( i=0;i {if(x==test[i]) return i;else if(x>test[i])low=i+1;else high=i-1;}if(i>=high) return -1;}int main(){int a[10]={1,2,3,4,5,6,7,8,9,10};int x=6,flag ;int low=0,high=10;flag=Csearch(a,x,0,10);if(flag==-1) printf("searching is failed!\n"); else printf("searching is success!\n") ;printf("This program is made by 10273206\n"); }运行结果为:②查找失败的例子为:#includeint Csearch(int test[],int x,int low,int high) {int i;for( i=0;i {if(x==test[i]) return i;else if(x>test[i])low=i+1;else high=i-1;}if(i>=high) return -1;}int main(){int a[10]={1,2,3,4,5,6,7,8,9,10};int x=11,flag ;int low=0,high=10;flag=Csearch(a,x,0,10);if(flag==-1) printf("searching is failed!\n"); else printf("searching is success!\n") ;printf("This program is made by 10273206\n"); }运行结果为:(3)程序为:#include#includeint Bsearch(int a[],int x,int low,int high) {int mid;if(low>high) return -1;mid=(low+high)/2;if(x==a[mid]) return mid;else if(x Bsearch(a,x,low,mid-1);elseBsearch(a,x,mid+1,high);}int Csearch(int test[],int x,int low,int high) {int i;for( i=0;i {if(x==test[i]) return i;else if(x>test[i])low=i+1;else high=i-1;}if(i>=high) return -1;}int main(){time_t start,end;double dif;int Bsearch(int a[],int x,int low,int high);int Csearch(int test[],int x,int low,int high);int a[10000],x,y,i,bn,flag;int low=0,high=10000,mid=0;printf("please enter number:\n");scanf("%ld",&x);for( i=0;i a[i]=i+1;time(&start);bn=Bsearch(a,x,0,10000);if(bn==-1) printf("%d is not in a !\n",x);else printf("%d is in a,suffix is %d\n",x,bn);time(&end);dif=difftime(end,start);printf("di gui method use time is:%f seconds\n",dif);time(&start);flag=Csearch(a,x,0,10000);if(flag==-1) printf("%ld is not in a !\n",x);else printf("%d is in a,suffix is %d\n",x,flag);time(&end);dif=difftime(end,start);printf("xun huan method use time is :%f seconds\n",dif);printf("This program is made by 10273206\n");}运行结果为:总结与思考通过实验我初步了解了递归算法到非递归算法的转换,递归算法在数据结构存储中用处很大。

C语言中的递归算法与应用

C语言中的递归算法与应用

C语言中的递归算法与应用递归算法是一种常见且重要的算法设计技巧,在C语言中得到广泛应用。

本文将介绍什么是递归算法,为何使用递归算法以及在C语言中如何实现递归算法,并结合实际应用场景进行讲解。

一、递归算法的定义与原理递归算法是一种自我调用的算法,通过将问题划分为更小的子问题来实现。

递归算法一般包括两部分:基本情况和递推关系。

基本情况是指递归的终止条件,当满足终止条件时递归停止。

递推关系是指将原问题转化为相同但规模更小的子问题,并通过递归调用解决子问题。

递归算法的实现原理可以用以下的逻辑来描述:1. 判断当前是否满足基本情况,满足则返回特定值;2. 否则,将原问题转化为一个或多个规模更小的子问题;3. 调用函数自身解决子问题,得到子问题的结果;4. 组合子问题的结果,得到原问题的解。

二、递归算法的优点与应用场景使用递归算法具有以下优点:1. 代码简洁易懂:递归算法能够以简洁的方式表达问题本质,提高代码的可读性;2. 解决问题的规模更小:通过递归调用子问题的解决方法,将原问题转化为更小规模的子问题,提高问题解决的效率;3. 可以解决一些复杂问题:递归算法在树、图等数据结构问题中具有广泛应用,能够高效解决这些复杂问题。

递归算法常见的应用场景包括:1. 数学计算:如斐波那契数列、阶乘等问题;2. 数据结构操作:如二叉树的遍历、图的遍历等问题;3. 搜索与回溯问题:如迷宫问题、八皇后问题等。

三、C语言中的递归算法实现在C语言中,使用递归算法实现的一般步骤如下:1. 定义递归函数:在函数原型中声明递归函数,并给出函数的返回值类型和参数列表;2. 编写基本情况处理逻辑:编写满足终止条件的处理逻辑,通常是直接返回特定值;3. 编写递推关系处理逻辑:编写将原问题转化为子问题的逻辑,并通过递归调用解决子问题;4. 通过递归调用解决子问题:在递归函数中调用自身,解决子问题并获取子问题的结果;5. 返回综合子问题结果:将子问题的解组合得到原问题的解,并返回。

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

递归算法在C/C++程序设计中的描述与实现[摘要]递归是函数实现的一个很重要的环节,对许多复杂的问题,递归能提供简单、自然的解法。

本文在对递归的概念进行介绍的基础上,重点讨论了递归的程序设计方法,并分析了递归函数的调用和回溯过程。

[关键词]递归函数调用C/C++1.引言递归是计算机科学中一种强有力的问题求解方法,用递归算法编写的程序结构清晰,具有很好的可读性,正确性容易验证。

但由于递归的设计思想比较巧妙,特别是对于规模较大的问题,掌握递归算法的设计分析和实现过程并非易事,因此,有必要对其进行深入探讨,分析其概念及设计方法和实现过程,以此加深对递归算法思想的进一步理解,学会正确应用递归解决实际问题的方法。

2.递归的概念如果一个对象部分地由自己组成或者是根据自己定义的,则称这个对象是递归的;在程序设计中,若一个过程直接地或间接地调用自身,则称这个过程是递归的过程。

在c,C++程序中,因为每次调用函数时,C/C++语言都会为参数和局部变量分配新的存储区空间,因此函数调用它自身是可能的。

这种类型的函数称为递归(recursive)函数。

当函数调用它自身时,这个过程称为直接递归(direct recursion)。

同样,函数能够调用第二个函数,反过来第二个函数也可以调用第一个函数。

这种类型的递归称为间接(indirect)递归。

通常如下两种情况会用到递归:(1)问题的定义是递归的。

许多数学上常用的概念是递归定义的。

如阶乘函数的常见定义:这种定义方法是用阶乘函数自身定义了阶乘函数。

由于n!和(n一1)!都是同一个问题的求解,因此可将n!用递归函数来描述。

程序代码如下:【例1】用递归函数编程求n的阶乘n!。

long factorial(int n){long result=0;if(0==n)result=1;elseresult=n*factorial(n-1);//调用自身return result;)(2)问题的解法是递归的。

例如有序表上的二分查找过程:确定查找区间的中心位置,用待查找数据与中心位置上的数据比较,若两者相等则查找成功;否则若前者小于后者,则把查找区间定为原查找区间的前半部分,继续重复之前的查找过程;若前者大于后者,则把查找区间定为原查找区间的后半部分,继续重复之前的查找过程。

在这里我们可以发现,对当前区间的查找过程与当前区间的前半部分或后半部分的查找过程是同一个问题的求解,因此可以将这一过程设计用递归函数来描述。

上述两种情况的求解过程中有一个共同的特点:都可以将待求解问题分解为形式更加简单的子问题,而子问题的求解方法与原问题的求解方法又是相同的。

有时一个问题的求解过程可以化为较小问题的求解过程,而较小问题的求解过程又可化为更小问题的求解过程,依次类推。

这种有规律地将原问题逐渐化小的过程,并且求解小问题的方法与求解大问题的方法相同,则称为递归求解过程。

由于在递归过程中,求解的问题越化越小,最后不需要再向下递归而能够直接得到一个最小问题的解;然后再逐层向上返回,依次得到较大问题的解,因此最终得到原有问题的解。

3.递归的设计方法能采用递归描述的算法通常有这样的特征:把规模大的、较难解决的问题分解成规模较小的、易解决的同一问题。

规模较小的问题又用同样的方法分解成规模更小的问题,并且小到一定程度可以直接得出它的解,从而得到原来问题的解。

特别地,当规模N=I时,能直接得解。

当一个问题存在上述构成递归的特征时,我们就可以考虑利用递归进行处理。

由此我们分析适宜用递归求解问题的充要条件是:其一,问题具有某种可借用的类同自身的子问题描述的性质;其二,某一有限步的子问题有直接的解存在。

当一个问题存在上述两个基本要素时,设计该问题递归算法的方法是:(1)设计递归公式。

即将一个问题化解为一个或多个子问题求解,且子问题和原问题具有相同的解法。

例如,前面【例1】的n!可化解为n*(n一1)!,其中,子问题(n一1)!和n!的解法相同。

(2)设计递归出口。

即递归终止条件(边界条件)。

递归最后一级的调用必须不能再进行递归,递归函数必须返回。

不能无穷递归。

在通常情况下,递归调用都是要受到条件控制的,而且在被调用的过程中,会对调用条件进行有规律的修改,即每递归一次要使递归趋于结束,直到满足边界条件,返回边界值,结束递归;然后按照原来的路径逐层返回,求出原问题的解。

由此可知,递归算法设计的关键在于递归描述(递归公式)和递归终止条件。

一般地,用递归方法进行“问题求解”时,具体需要依次进行下列三个步骤。

(1)化解问题,求得算法当问题化解成子问题后,有的可以写出一个迭代公式。

如阶乘n!,可写迭代公式f(n)=n*f(n-1)。

有的可以归于一个操作的循环。

例如,若将一个十进制数n转换为二进制数输出,则可有下列循环:①输出n的2的余数(n%2);②将n向右移一位或求n/2,若结果为0,输出后结束;若结果不为0,则转步骤①。

程序代码如下:【例2】将十进制数U转换为二进制输出。

#include<iostream>using namespace std;void d2b(int n) ;int main(){d2b(147);return 0;}void d2b(int n){if((0==n)||(1==n))cout<<n;else{d2b(n/2);cout<<n%2;//注意输出语句与递归调用语句的位置关系}}程序运行结果:10010011无论是上述的哪一种情况,我们都可以看出每次递归在规模上都有所缩小(通常是减半),而且相邻两次递归之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入)。

(2)规划递归路线有些问题无须返回值,它要求完成相应的递归操作,类似递推,称为递归过程。

无论是递归过程还是递归函数,递归路线可以有一条或多条。

如【例1】中的Factorial函数,自身调用语句只有一条,也就是递归路线只有一条。

若递归函数或过程中自身调用语句不止一条,则可形成多条递归路线。

但是每次递归的时候只有一条路线起作用。

如二分查找用递归算法实现时,由于待查找数据与中心位置数据的比较结果不止一个,所以就会形成多条递归路线,但每次调用只有一条路线会被执行到。

需要说明的是,由于递归调用是在栈内存空间中完成的,而栈的工作原理是先进后出,因此当递归路线中需要输出时,输出语句放在递归函数调用语句之前和之后次序是刚好相反的。

如【例2】函数d2b中,若语句“cout<<n%2;”,放在递归调用语句“d2b(n/2);”之前,则递归后“cout<<n%2;”从左至右输出最低位到最高位的值。

显然,这样输出次序是颠倒的。

应将语句“eout<<n%2;”放在递归调用语句之后,利用栈的先进后出原理,从而输出正确的次序。

(3)确定形参,设计递归终止条件在问题的规模极小时必须直接给出解答而不再进行递归调用,因而每次递归调用都是有条件的(以规模未达到直接解答的大小为条件),无条件递归调用将会成为死循环而不能正常结束。

递归过程或递归函数的参数值在递归过程中必须是按规律变化的,且参数值的增,减方向应与递归终止条件相匹配,这样才能控制递归调用。

如【例2】递归函数d2b中的形参n,每次递归调用时n值减半,直到n等于0或1为止,递归终止。

一般递归函数设计的格式为:说明:若递归路线为多条,则else分支不止一个。

4.递归过程递归函数在实现过程中需多次进行自我调用,因而正确理解递归调用及回溯过程是十分重要的。

由函数调用的内部机制我们知道函数调用是在栈内存空间中完成的,栈的工作原理是先进后出。

当调用一个函数时,整个调用过程分为三步进行:调用初始化、执行函数调用、调用后处理。

高级程序设计语言利用堆栈保存递归函数调用时的信息,系统中用于保存递归函数调用信息的堆栈称为运行时栈。

递归函数调用时,系统的运行时栈会将函数的返回地址、本次函数调用时的实参值、被调用函数的局部变量值三种信息构成一个工作记录存入栈中,在每进入下一层递归调用时就建立一个新的工作记录,并把这个工作记录进栈成为运行时栈的新栈顶;每退出一层递归调用,即函数调用返回时,系统运行时栈需要保存函数的返回值、释放实参和局部变量的内存空间,释放栈空间,然后按照之前所保存的返回地址返回,完成一个工作记录的退栈。

因为栈顶的工作记录必定是在当前运行层的工作记录,所以栈顶的工作记录称为活动记录。

由于函数的地址是系统动态分配的,调用函数的返回地址因此也是动态变化的,不好给出具体数值,所以我们仅以递归函数调用时形参的内存地址作为考查对象,来分析一下递归函数的调用和回溯过程。

为了能看清楚递归函数在运行过程中调用和返回的情况,这里将【例1】中函数factorial的代码修改如下(斜体阴影部分),其中begin、end两个静态局部变量分别表示递归函数的调用序号和返回序号,用&n获取参数n的地址。

#include<iostream>using namespace std;long factorial(int n);int main(){cout<<”4!=” <<factorial(4)<<endl;return O:}long factorial(int n){ long result=0;if(O==n)result=1;elseresult=n*factorial(n-1);return result;}程序运行结果如下:调用序号1 0012FF2C factorial(4)调用序号2 0012FECC factorial(3)调用序号3 0012FE6C factorial(2)调用序号4 0012FEOC factorial(1)调用序号5 0012FDAC factorial(0)返回序号1 0012FDAC factorial(0)=1返回序号2 0012FEOC factorial(1)=1返回序号3 0012FE6C factorial(2)=2返回序号4 0012FECC factorial(3)=6返回序号5 0012FF2C factorial(4)=244!=24由以上运行结果可见,尽管函数factorial递归调用时的形参都是n,但每次调用系统会为其分配不同的内存空间。

程序第一次调用factorial函数计算4 !,即调用函数factorial(4),形参n接受传递的实参值4,因n=4,不等于0,故执行“result=4*factorial(3);”,并未直接得到factorial(4)的结果,而是要继续调用factorial(3)。

相关文档
最新文档