C语言程序中递归算法的使用实例教程

 更新时间:2016年04月25日 15:28:13   作者:wuyudong  
这篇文章主要介绍了C语言程序中递归算法的使用实例教程,递归经常被用来进行阶乘和比较大小等计算工作,文中举的都是一些基础的例子,需要的朋友可以参考下

1.问题:计算n!
数学上的计算公式为:

n!=n×(n-1)×(n-2)……2×1

使用递归的方式,可以定义为:

2016425152204144.jpg (313×64)

以递归的方式计算4!

F(4)=4×F(3)            递归阶段

F(3)=3×F(2)

F(2)=2×F(1)

F(1)=1  终止条件

F(2)=(2)×(1)    回归阶段

F(3)=(3)×(2)

F(4)=(4)×(6)

24                 递归完成

以递归方式实现阶乘函数的实现:

int fact(int n) {
  if(n < 0)
    return 0;
  else if (n == 0 || n == 1)
    return 1;
  else
    return n * fact(n - 1);
}

2.原理
下面来详细分析递归的工作原理

先看看C语言中函数的执行方式,需要了解一些关于C程序在内存中的组织方式:

堆的增长方向为从低地址到高地址向上增长,而栈的增长方向刚好相反(实际情况与CPU的体系结构有关)。

当C程序中调用了一个函数时,栈中会分配一块空间来保存与这个调用相关的信息,每一个调用都被当作是活跃的。栈上的那块存储空间称为活跃记录或者栈帧

栈帧由5个区域组成:输入参数、返回值空间、计算表达式时用到的临时存储空间、函数调用时保存的状态信息以及输出参数,参见下图:

2016425152248859.jpg (422×400)

可以使用下面的程序来检验:

#include <stdio.h>
int g1=0, g2=0, g3=0;
int max(int i)
{
  int m1 = 0, m2, m3 = 0, *p_max;
  static n1_max = 0, n2_max, n3_max = 0;
  p_max = (int*)malloc(10);
  printf("打印max程序地址\n");
  printf("in max: 0x%08x\n\n",max);
  printf("打印max传入参数地址\n");
  printf("in max: 0x%08x\n\n",&i);
  printf("打印max函数中静态变量地址\n");
  printf("0x%08x\n",&n1_max); 
//打印各本地变量的内存地址
  printf("0x%08x\n",&n2_max);
  printf("0x%08x\n\n",&n3_max);
  printf("打印max函数中局部变量地址\n");
  printf("0x%08x\n",&m1); 
//打印各本地变量的内存地址
  printf("0x%08x\n",&m2);
  printf("0x%08x\n\n",&m3);
  printf("打印max函数中malloc分配地址\n");
  printf("0x%08x\n\n",p_max); 
//打印各本地变量的内存地址
  if(i) return 1;
  else return 0;
}
int main(int argc, char **argv)
{
  static int s1=0, s2, s3=0;
  int v1=0, v2, v3=0;
  int *p;  
  p = (int*)malloc(10);
  printf("打印各全局变量(已初始化)的内存地址\n");
  printf("0x%08x\n",&g1); 
//打印各全局变量的内存地址
  printf("0x%08x\n",&g2);
  printf("0x%08x\n\n",&g3);
  printf("======================\n");
  printf("打印程序初始程序main地址\n");
  printf("main: 0x%08x\n\n", main);
  printf("打印主参地址\n");
  printf("argv: 0x%08x\n\n",argv);
  printf("打印各静态变量的内存地址\n");
  printf("0x%08x\n",&s1); 
//打印各静态变量的内存地址
  printf("0x%08x\n",&s2);
  printf("0x%08x\n\n",&s3);
  printf("打印各局部变量的内存地址\n");
  printf("0x%08x\n",&v1); 
//打印各本地变量的内存地址
  printf("0x%08x\n",&v2);
  printf("0x%08x\n\n",&v3);
  printf("打印malloc分配的堆地址\n");
  printf("malloc: 0x%08x\n\n",p);
  printf("======================\n");
  max(v1);
  printf("======================\n");
  printf("打印子函数起始地址\n");
  printf("max: 0x%08x\n\n",max);
  return 0;
}

栈是用来存储函数调用信息的绝好方案,然而栈也有一些缺点:

栈维护了每个函数调用的信息直到函数返回后才释放,这需要占用相当大的空间,尤其是在程序中使用了许多的递归调用的情况下。除此之外,因为有大量的信息需要保存和恢复,因此生成和销毁活跃记录需要消耗一定的时间。我们需要考虑采用迭代的方案。幸运的是我们可以采用一种称为尾递归的特殊递归方式来避免前面提到的这些缺点。


3.斐波那契数列

#include <stdio.h> 
 
int fibonacci(int a){//fibonacci数列,第一二项为1;后面的每一项为前两项之和 
  if (a == 1 || a == 2) 
  { 
    return 1; 
  }else{ 
    return fibonacci(a - 1) + fibonacci(a - 2); 
  } 
} 
 
void main(){ 
  printf("%d\n",fibonacci(40)); 
} 

 
4.递归将整形数字转换为字符串

#include <stdio.h> 
 
int toString(int i, char str[]){//递归将整形数字转换为字符串 
  int j = 0; 
  char c = i % 10 + '0'; 
  if (i /= 10) 
  { 
    j = toString(i, str) + 1; 
  } 
  str[j] = c; 
  str[j + 1] = '\0'; 
  return j; 
} 
 
void main(){ 
  char str[100]; 
  int i; 
  printf("enter a integer:\n"); 
  scanf("%d",&i); 
  toString(i,str); 
  puts(str); 
} 

5.汉诺塔

#include <stdio.h> 
 
void hanoi(int i,char x,char y,char z){ 
  if(i == 1){ 
    printf("%c -> %c\n",x,z); 
  }else{ 
    hanoi(i - 1,x,z,y); 
    printf("%c -> %c\n",x,z); 
    hanoi(i - 1,y,x,z); 
  } 
} 
 
void main(){ 
  hanoi(10,'A','B','C'); 
} 

 
6.四个数找最大

int max(int a, int b, int c, int d){ 
  if(a > b && a > c && a > d){ 
    return a; 
  }else{ 
    max(b,c,d,a); 
  } 
} 

7.猴子吃桃
每天吃一半再多吃一个,第十天想吃时候只剩一个,问总共有多少:

int chitao(int i){//猴子吃桃,每天吃一半再多吃一个,第十天想吃时候只剩一个 
  if(i == 10){ 
    return 1; 
  }else{ 
    return (chitao(i + 1) + 1) * 2; 
  } 
} 

相关文章

  • C++11的functional模块介绍和使用案例

    C++11的functional模块介绍和使用案例

    functional模块是C++ 11提供了一组函数对象和算法,用于增强C++的函数式编程能力,本文主要介绍了C++11的functional模块介绍和使用案例,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • Qt专栏之模态与非模态对话框的实现

    Qt专栏之模态与非模态对话框的实现

    这篇文章主要介绍了Qt专栏之模态与非模态对话框的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • C++驱动bash的实现代码

    C++驱动bash的实现代码

    这篇文章主要介绍了C++驱动bash的实现代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-11-11
  • OpenCV实现图像拼接案例

    OpenCV实现图像拼接案例

    这篇文章主要介绍了OpenCV实现图像拼接案例,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-08-08
  • C++设计模式之组合模式(Composite)

    C++设计模式之组合模式(Composite)

    这篇文章主要为大家详细介绍了C++设计模式之组合模式Composite,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-04-04
  • C++中关键字Struct和Class的区别

    C++中关键字Struct和Class的区别

    这篇文章主要介绍了C++中关键字Struct和Class的区别,本文用大量实例讲解了Struct和Class的区别,需要的朋友可以参考下
    2014-09-09
  • C++内存管理详解使用方式

    C++内存管理详解使用方式

    内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能更大的自由,C++菜鸟的收获则是一遍—遍的检查代码和对C++的痛恨,但内存管理在C++中无处不在,内存泄漏几乎在每个C++程序中都会发生,要想成为C++高手,内存管理这关是必须过的
    2022-04-04
  • C语言基本概念宏定义中的#和##教程

    C语言基本概念宏定义中的#和##教程

    这篇文章主要为大家介绍了C语言基本概念宏定义中的#和##教程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • C语言详细图解浮点型数据的存储实现

    C语言详细图解浮点型数据的存储实现

    使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。您可能需要存储各种数据类型的信息,操作系统会根据变量的数据类型,来分配内存和决定在保留内存中存储什么
    2022-05-05
  • C语言使用rand函数生成随机数

    C语言使用rand函数生成随机数

    这篇文章介绍了C语言使用rand函数生成随机数的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-12-12

最新评论