其实一直到如今我都不知道本身有没有学会递归,由于作题的时候我也是拈轻怕重挑着我擅长的题作,因此这方面一直没有获得突破性的提升。ios
由于递归的概念很好理解,可是实际操做起来就会让人很迷糊,好比说汉诺塔。函数
但昨天老师在群里面分享了四节递归课程,我决定从新拾起我之前没有干完的活。spa
那么咱们就先从汉诺塔这个经典的递归开始学吧,之前我在看这道题的时候,老是会想着去模拟这整个过程。code
就好比说我会去网上下载一些汉诺塔的小游戏玩,美曰其名为模拟过程加深理解,其实就是打着幌子在玩游戏。blog
或者我会在纸上面画图模拟整个过程,并且时常画着画着就画糊涂了。递归
可能你很疑惑,为何要模拟过程呢?游戏
由于我不理解他为何只在调用他本身时把参数的位置改一改就能够获得所有过程。ci
但如今看来,着实没有必要,咱们只须要知道咱们得把这n-1个盘子移动到b盘,再把最底下的盘子移动到c盘,再把n-1个盘子移动到c盘就行了。io
也就是说,咱们把它分为两个总体,n-1个盘子为一个总体,最底下的盘子是一个总体,可是那n-1个盘子是怎么移动的呢?class
我能告诉你的只有他会重复以前的步骤,把n-1分解成为n-2个盘子和第n-1个盘子,n-2个盘子怎么移动的呢,分解成n-3个盘子和第n-2个盘子呗,后面的也以此类推。
直到咱们分解到最顶上那个最小的盘子的时候,只须要把它从a盘拿到c盘就能够了(这是一个出口,也就是说咱们的栈已经满了,须要一个判断出口,把那些堆进栈的东西都一个个拿出去)
那么如今咱们知道该怎么把这一个大问题分解成几个小问题,也知道出口是什么,代码就很好写了。
#include<iostream> #include<cstdio> using namespace std; int a,ans=0;//ans是用来记录总共移动的次数的 void hnt(int n,char a,char b,char c){//递归函数 if(n==1){//出口判断 ans++;//移动的时候ans就+1 cout<<a<<" "<<c<<endl;//等到最后一个小盘子的时候,咱们就直接让它从a盘去c盘 } else{ hnt(n-1,a,c,b);//分解问题到n-1 ans++;//移动的时候ans就+1 cout<<a<<" "<<c<<endl;//解决完n-1就只剩第n个盘子了,咱们就把第n个盘子从a盘直接拿到c盘 hnt(n-1,b,a,c);//再把这n-1从b盘上面转到c盘上面 } } int main(){ cin>>a;//输入要移动的盘子数量 hnt(a,'A','B','C'); cout<<ans<<endl;//输出一共须要移动多少次 return 0; }
为何明明咱们须要用这三个柱子来进行操做,但是输出的时候只用输出a和c呢?
不知道你有没有注意到咱们在进行递归的时候,调用函数的参数咱们让他改变了。
因此a、b、c每一个变量里面的字符都不同了,因此只要输出a和c就能够达到咱们想要的结果。
你可能会想,咱们把他改变了,他会是怎么运行的呢?要不我计算试试看?
那么我只能告诉你,千万不要计算,不要去深究这个问题。由于你会发现你越算越糊涂,越算越不会。
只须要知道这个为何要这样算,不须要知道她是怎么算的。
也就是说咱们只要计算方法和结果,过程不重要。