小伙伴们大家好,今天来学习一下递归函数的汉诺塔问题吧
首先,我们要先了解递归函数
一、递归函数
1.什么是递归函数?
简单来讲,递归函数就是函数本身自己调用自己,那么函数又是什么呢?
以最熟悉的main函数为例,我们学C++的时候,通常会写如下格式:
#include <stdio.h> //这行是头文件,不同的头文件可以用不同的函数
int main() //这里就是一个main函数
{
//这里是你要编写程序的内容
return 0;
}
(这是个小细节如下)
所以我们平时用来练习的就是一个main函数,而且是一个整型类型的函数,而这也是最后一句话为什么要加一句 return 0; 了,因为它最后要返回整数类型,其它整数也可以,但是大家规定为0,这是C++自带的函数
但是,如果我们想实现一个操作,而系统中没有可以直接拿来用的函数,我们一般就会自己写一个
函数,然后自己用(本篇主要讲解递归函数,关于函数的其它知识,只在用到时提起)
这个时候,如果你遇到一些比较复杂的问题,就可以用递归函数来解决,原本几十行代码,可能用递归函数只要几行就解决掉了,当然这是一种“大事化小”的思想
!!!注意: 并不是所有函数都可以用递归函数,也不是复杂的题目用递归简单
我们先来练习一道,题目如下:
用递归函数的方法,计算n的阶乘
#include <stdio.h>
int Fact(int n) //注意这里一定要加函数类型
{
if(n == 0)
return 1;
else
return n * Fact(n - 1);
}
int main()
{
int n = 0; //注意这里有个细节之前没有提到,我们一般定义变量会先赋值,否则定义的变量是个随机数
scanf("%d",&n);
int sum = Fact(n);
printf("%d",sum);
return 0;
}
它的实现方法是这样的:
例如:当 n = 5 的时候,你输入了5,然后进入了你写的阶乘函数,
第一次判断:n = 5 ,n != 0,于是进入 n*Fact(n - 1),就是5*Fact(n - 1)
第二次判断:n = 4,n != 0,于是进入 n*Fact(n - 1),就是4*Fact(n - 1)
第三次判断:n = 3,n != 0,于是进入 n*Fact(n - 1),就是3*Fact(n - 1)
第四次判断:n = 2,n != 0,于是进入 n*Fact(n - 1),就是2*Fact(n - 1)
第五次判断:n = 1,n != 0,于是进入 n*Fact(n - 1),就是1*Fact(n - 1)
第六次判断:n = 0,n == 0,于是 return 1
之后你最后一次的时候,函数回归:
第一次回归:由于return 1 ,此时Fact(n - 1)为1,1*Fact(n - 1) = 1*1
第二次回归:2*Fact(n - 1),此时上一次的结果Fact(n - 1)为1,2*Fact(n - 1) = 2*(1*1)
第三次回归:3*Fact(n - 1),此时上一次的结果Fact(n - 1)为2,2*Fact(n - 1) =3* 2*(1*1)
第四次回归:4*Fact(n - 1),此时上一次的结果Fact(n - 1)为6,2*Fact(n - 1) = 4*3*2*(1*1)
第五次回归:5*Fact(n - 1),此时上一次的结果Fact(n - 1)为24,2*Fact(n - 1) = 5*4*3*2*(1*1)
这就是递归全过程
2.递归函数的限制条件
- 存在停止函数递归的条件,上面的例子很明显,就是那条判断语句 if (n == 0)
- 每次递归都接近该条件
!!!注意:如果写递归函数没有停止条件一直自己调用自己,那么就会栈溢出,程序会出错
二、汉诺塔问题
1.什么是汉诺塔?
汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
这里由于计算机算64片汉诺塔数据过于庞大,次数过多,结果很久才能出来,因此我们实现的是输入一个较小的数字让其实现输出每一次圆盘的走向,这里用图来表示一下,让大家辅助理解:
位置1 位置2 位置3
位置1 位置2 位置3
这个时候,大家如果还不理解,先从两个圆盘画起,之后大家在画一画四个圆盘,我们就能得出一个规律:
每次最底下的圆盘放过去之后,有(n - 1)个圆盘在中间位置的柱子上
剩下这(n - 1)个圆盘我们需要通过位置一这个转站点到位置三
2.通过如上思想(橘色字体)编写代码
这个时候我们用递归函数的思想,代码如下:
#include <stdio.h>
void move(char wz1, char wz2)
{
printf("%c >> %c\n",wz1,wz2); //这里是输出每一次圆盘的走向
}
//这里的顺序是:(n个圆盘)(起点)(转站点)(终点)
void Hannuota (int n, char wz1, char wz2, char wz3)
{
if (n == 1) //一个圆盘的时候只要一步,从A移动到C
{
move(wz1, wz3);
}
else
{
Hannuota (n-1, wz1, wz3, wz2); //通过位置三把剩下(n - 1)个盘子移到位置二上
move(wz1,wz3); //这里可以实现最后一个圆盘从起点位置到了最终的位置三
Hannuota(n-1, wz2, wz1, wz3);//剩下(n - 1)个圆盘要在位置二上通过位置一,移动到最终的位置三上
}
}
int main()
{
int n;
scanf("%d",&n);
Hannuota(n,'A','B','C'); //调用汉诺塔函数
return 0;
}
大家不清楚可以多画图,多思考 ,理清逻辑才能更好理解
学习递归的时候看到一句话,可能对你有帮助,递归大多不要求搞清楚实际程序运行,递归只是执行步骤
今天的内容就结束啦,认真的学会TA的你真的很酷!加油呀!