其實一直到如今我都不知道本身有沒有學會遞歸,由於作題的時候我也是拈輕怕重挑着我擅長的題作,因此這方面一直沒有獲得突破性的提升。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就能夠達到咱們想要的結果。
你可能會想,咱們把他改變了,他會是怎麼運行的呢?要不我計算試試看?
那麼我只能告訴你,千萬不要計算,不要去深究這個問題。由於你會發現你越算越糊塗,越算越不會。
只須要知道這個爲何要這樣算,不須要知道她是怎麼算的。
也就是說咱們只要計算方法和結果,過程不重要。