网上的汉诺塔教学很多了,虽然非常详细,但我以前在学习时,却因为思维方式的不同而难以理解。
汉诺塔只是递归中的一个简单的题,但其包含的知识,却是所有递归里面共有的。
汉诺塔 的问题描述这里就不再阐述了,接下来主要讲解思路:
函数代码如下:
void hanoi(int n, char a = 'a', char b = 'b', char c = 'c') {//输出 汉诺塔为n层时,输出把所有圆盘从左杆移到右杆所需的所有步骤。
if (n == 1) {
printf("%c->%c\n", a, c);
return;
} else {
hanoi(n - 1, a, c, b);
hanoi(1, a, b, c);
hanoi(n - 1, b, a, c);
}
}
讲解如下:
创建的函数hanoi为:输出 汉诺塔为n层时,输出把所有圆盘从左杆移到右杆所需的所有步骤。
既然函数的功能是这样,那为什么不直接用呢?
这就涉及到递归函数我认为的本质了,或者说函数的本质。
函数就像一块砖,哪有需要往哪搬。
只有理解了递归函数的本质,才能知道怎么去运用。
对于汉诺塔问题,可以跳过现象看本质:
需要明确一点:对于最底层最大的圆盘,是不影响其他任何圆盘的移动的。
如果我们能:1:将上面的所有圆盘,都移动到中间杆:上
2:最大的圆盘,就可以轻松从左杆移到右杆了
3:此时再把中间所有的圆盘移到右杆就可以了
解决问题:
对于1:若要将除了最底层的圆盘都移动,就可以抹除最后一块,此时剩下n-1块圆盘。而要移动到中间杆上,则需要对b与c的位置进行调换。(为了防止混淆,我都说的是左中右杆,而不是abc杆);因为想让函数是输出n-1层汉诺塔从左移到中的所有步骤!那么中间杆b,就应该放到最右边,c放中间不管。代码:hanoi(n - 1, a, c, b);
对于2:因为只移动一个圆盘,那么此时应当输出一层汉诺塔从左移到右所需的步骤。代码:hanoi(1, a, b, c);
对于3:因为要把中间所有的圆盘移到右杆,此时中间有n-1个,所以为n-1层汉诺塔。而因为想让函数输出n-1层汉诺塔从中移到右的所有步骤,就需要把a,b调换。代码:hanoi(n - 1, b, a, c);
对于终止条件,因为汉诺塔是越移动,层数越少的。所以n为下降趋势。在n<=0时,汉诺塔没有意义。所以终止条件应设置在n==1处,直接输出左移到右,并返回。
总结:
汉诺塔问题讲解结束。这只是一个入门的基础问题,但包含的知识点却意义重大!通过这个题,可以加深对递归函数,乃至所有函数的理解。
函数就像一块砖,哪里需要往哪里搬!
不知你们是否可以在未学递归函数前,就能意识到有递归函数存在呢?先不管是否可以写出正确的代码,如果能意识到,说明真正理解了函数的意义。
理论上来说,所有能用到函数意义的地方,都可以调用函数!比如循环;比如函数里调其他函数;比如函数里调自己;比如把函数作为参数传入;递归虽然在之前的学习中没有学到,但递归所包含的意义却早已无处不在!
在下第一次写博客,如有语言不详细,描述过简略之处,还请多指出!
欢迎各位大佬指正!
2023/7/21 00:49 家卧 感慨
全部代码如下:
#include <iostream>
using namespace std;
#include "bits/stdc++.h"
#include<cstdio>
#include <iomanip>
#include <valarray>
void hanoi(int n, char a = 'a', char b = 'b', char c = 'c') { //输出 汉诺塔为n层时,输出把所有圆盘从左杆移到右杆所需的所有步骤。
if (n == 1) {
printf("%c->%c\n", a, c);
return;
} else {
hanoi(n - 1, a, c, b);
hanoi(1, a, b, c);
hanoi(n - 1, b, a, c);
}
}
int main() {
int n;
cin >> n;
hanoi(n);
}