目录
一.什么是递归
程序调用自身的编程技巧称为递归(recursion).
盗梦空间不知道大家看过没有,主角一行人为了完成一个任务的解决,逐步深入层层梦境,然后从外到里,再从里到外,层层梦境退出来.
当然两者不是完全相同,只是有一定相似性,递归还有限定条件,而且往往是进行相同的操作(也就是将一个大问题分解成小问题),这个需要我们做多点题来逐步加深理解.
二.递归的两大基本条件
三.递归练习
(大事化小,牢记心中!!!)
#include <stdio.h>
void Print(int x)
{
if (x > 10)
{
Print(x / 10);
}
printf("%d ", x % 10);
}
int main()
{
int x = 0;
scanf("%d", &x);
Print(x);
return 0;
}
#include <stdio.h>
int my_strlen(char* str)
{
if (*str == '\0')
return 0;
else
return my_strlen(str + 1) + 1;
}
int main()
{
char str[] = "Breaking bad";
int len = my_strlen(str);
printf("%d", len);
return 0;
}
Lg.3
汉诺塔问题
相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏.
该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘.
游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好.
操作规则:
1.每次只能移动一个盘子,操作过程中盘子可以置于A、B、C任一杆上.
2.在移动过程中三根杆上都始终保持大盘在下,小盘在上.
如图所示,这里只列举了只有三个金盘的情况,目标则是在保证移动过程中,小金盘始终在大金盘之上,然后将A杆上的金盘全部移动到C杆上.
思路分析:
设金盘数目为n
于是,我们便着手构造汉诺塔函数,设定四个参数,n为盘子的个数.
#include <stdio.h>
void move(int n ,char cur_stick, char target_stick)
{
printf("将第%d个盘子从%c杆 ——> %c杆\n", n, cur_stick, target_stick);
}
void Hanoitower(int n, char cur_stick, char assist_stick, char target_stick)
{
if (n == 1)
move(1,cur_stick ,target_stick);
else
{
Hanoitower(n - 1, cur_stick, target_stick, assist_stick);
move(n,cur_stick, target_stick);
Hanoitower(n - 1, assist_stick, cur_stick, target_stick);
}
}
int main()
{
int n;
scanf("%d", &n);
Hanoitower(n, 'A', 'B', 'C');
return 0;
}
移动的总次数:
前面我们依旧提到过,想要将N个盘子全部移动到目标杆,关键就是将第N个(最底下的盘子移过去),仔细思考一下,我们可以比较轻松理解到,将N-1个盘子从当前杆移动到辅助杆,再从辅助杆移动到目标杆,两个的步骤绝对是完全相同的.
所以,F(n) = 2*F(n - 1) + 1,是一个递推公式
通过数学归纳法,我们可以轻松得到,F(n) = 2*n - 1.轻松就可以得到移动的总次数.
Lg.4
青蛙跳台阶问题
一只青蛙一次可以跳一级台阶,或者二级台阶,请问它跳k级台阶有多少种方法?
思路分析:
假设小青蛙已经跳到最后一步,就差临门一脚,就成功跳完所有台阶
这时候我们会发现,有两种情况
第一种,是还差一个台阶,和跳n - 1 个台阶没两样,就差多跳1个台阶
第二,是还差两个台阶,那和跳n - 2个台阶没两样,就差多跳2个台阶
举例说明:
我跳3级台阶的方法,实际上就是
跳1级台阶的方法个数(跳1个台阶,差2个台阶,再跳一次2个台阶,总共为1)
+
跳2级台阶的方法个数 (跳2个台阶,有2种方法,再跳一次1个台阶,总共为2)
=
3种方法
....类似下去,我们便可以得到这也是一道递归的问题,而且和斐波拉契数列问题相同.
详细代码如下:
#include <stdio.h>
int move_step(int x)
{
if (x == 1)
return 1;
else if (x == 2)
return 2;
else
return move_step(x - 1) + move_step(x - 2);
}
int main()
{
int n;
scanf("%d", &n);
printf("%d", move_step(n));
return 0;
}
四.递归与迭代
我们从一道题开始入手,即经典的斐波拉契数问题.
五.一些总结和思考
通过上面几道练习,我们已经简单了解到什么是递归
4.递归实现的前提是函数栈帧开辟需要申请空间,通过向栈帧压进变量,返回函数栈帧的时候,自然就能重新获得原来这个变量.