目录

  • 1 第一章 C语言简介
    • 1.1 C语言前世今生
    • 1.2 主流开发环境介绍
    • 1.3 第一个小程序解析
    • 1.4 常见编译错误
    • 1.5 章节知识点小结
  • 2 算法基础
    • 2.1 算法-程序的灵魂
    • 2.2 算法的描述-流程图
  • 3 数据类型与运算符
    • 3.1 数据描述
    • 3.2 运算符和表达式1
    • 3.3 运算符和表达式2
    • 3.4 章节知识点小结
  • 4 顺序结构程序设计
    • 4.1 输入和输出
    • 4.2 顺序结构程序设计
    • 4.3 章节知识点小结
  • 5 选择结构程序设计
    • 5.1 关系运算符和关系表达式
    • 5.2 逻辑运算符和逻辑表达式
    • 5.3 if语句
    • 5.4 条件运算符
    • 5.5 switch语句
    • 5.6 章节知识点小结
  • 6 循环结构程序设计
    • 6.1 while循环结构
    • 6.2 do_while循环结构
    • 6.3 for循环结构
    • 6.4 循环的嵌套
    • 6.5 break语句和continue语句
    • 6.6 章节知识点小结
  • 7 数组
    • 7.1 一维数组
    • 7.2 二维数组
    • 7.3 字符数组
    • 7.4 章节知识点小结
  • 8 函数
    • 8.1 子程序设计
    • 8.2 函数定义
    • 8.3 函数的调用
    • 8.4 局部变量和全局变量
    • 8.5 参数传递
    • 8.6 函数递归调用
    • 8.7 章节知识点小结
  • 9 指针
    • 9.1 指针的基本概念
    • 9.2 指针变量的定义及引用
    • 9.3 通过指针引用数组元素
    • 9.4 指向多维数组的指针和指针变量
    • 9.5 用指向数组的指针作函数参数
    • 9.6 指针与字符串
    • 9.7 函数指针和指针函数
    • 9.8 章节知识点小结
  • 10 用户自己建立数据类型
    • 10.1 定义和使用结构体变量
    • 10.2 使用结构体数组
    • 10.3 结构体指针
    • 10.4 章节知识点小结
  • 11 编译预处理
    • 11.1 宏定义预处理
    • 11.2 文件包含预处理
    • 11.3 条件编译预处理
    • 11.4 章节知识点小结
  • 12 文件
    • 12.1 文件的基本知识
    • 12.2 文件的基本操作
    • 12.3 章节知识点小结
函数递归调用




递归调用概念


所谓递归即程序对自身的调用,是一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型的复杂问题层层转化为一个与原问题相似但规模较小的问题来求解。

经典案例1

汉诺塔是一个可以使用递归解决的经典问题,它源于印度一个古老传说:大梵天创造世界的时候做了三根金刚石柱子,一根柱子上从下往上按照从大到小的顺序摞着64片黄金圆盘,大梵天命令婆罗门把圆盘从下面开始按照从大到小的顺序重新摆放在另一根柱子上,并规定,小圆盘上不能放大圆盘,三根柱子之间一次只能移动一个圆盘。问一共需要移动多少次,才能按照要求移完这些圆盘

案例分析

假设一共有n个圆盘,移动的次数为f(n)

1)当n=1时,只需将圆盘从A移动到C,移动结束。f(1)=1

2)当n=2时,将A柱顶层的圆盘移动到B柱,将底层的圆盘移动到C柱,再将B柱上的圆盘移动到C柱,移动结束。f(2)=3

3n=3时,将A柱自顶向下的第一个圆盘移动到C柱,第二个圆盘移动到B柱,将C柱上的圆盘移到B柱,将A柱的最后一个圆盘移动到C柱,将B柱上的第一个圆盘移动到A柱,将B柱的圆盘移动到C柱,再将A柱的圆盘移动到C柱,移动结束。此时f(3)=7

……

依次类推,可以得出规律:f(n+1)=f(2n)+1

根据公式可知,该问题符合递归的规律,因此该问题可使用递归方式求解。

经典案例2

兔子数列又称斐波那契数列、黄金分割数列,因数学家列昂那多·斐波那契以兔子繁殖为例而引出,故得此名,具体描述如下:一对兔子在出生两个月后,每个月能生出一对小兔子。现有一对刚出生的兔子,如果所有兔子都不死,那么一年后共有多少对兔子?

案例分析

案例要求编程解决此问题,并把最终结果输出到屏幕上。

对该问题进行分析,以n表示月份,可知第n个月时兔子的数量等于第n-1个月时兔子的数量,加上第n-2个月时兔子的数量,以f(n)表示每个月兔子的数量,则满足以下公式:

f(n)=f(n-1)+f(n-2)      (n>1)

f(n)视为一个关于月份的函数,根据上述公式可知,在求解当月兔子数量时,需要再次借用该函数自身。


递归调用形式

递归有两种形式,即:直接递归和间接递归。

直接递归是指在一个函数中包含对其本身的调用,而间接递归是指函数P在调用其他函数Q时,而函数Q又直接或间接地调用函数P。


程序中不应该出现无终止的递归调用,而只应出现有限次数的、有终止的递归调用。一般使用if语句进行控制,当某一条件成立时继续执行递归调用,否则终止递归调用。

递归问题求解一般需要满足以下三个条件:

  1. 原问题能够向另一个相对更简单的问题转化;

  2. 转化后的问题和原来问题求解类似;

  3. 转化能够有一个终止的条件。


例8.7.1】计算Fibnbcci数列。

递归函数形式:

long fib(n)

int n;

{

long f;

if(n==0) f=0;

else if(n==1) f=1;

else f=fib(n-1)+fib(n-2);    // 此处调用其本身函数,为直接递归 

return f;

}

............................

上述程序不完整,同学可以自行补充主函数并完成调用