漢諾塔問題 關於遞迴和回溯的,漢諾塔遞迴函式問題

2022-02-04 22:47:02 字數 3919 閱讀 6309

1樓:

理解計算機的遞迴過程,和以前數學中的遞推證明非常接近。

數學的遞推證明的思想是,假定n-1的時候是正確的,證明n也是正確就可以了。

遞迴過程的思想是,如果已經有了解決

當然,還要處理一下遞迴的結束條件(當n=1的時候),否則遞迴就不會結束了。

利用遞迴解決漢諾塔,其最巧妙之處在於實參和形參的不斷變幻。就是形參x, y ,z所對應的實參,在遞迴過程中是不斷改變的。

注意:形參

move(int n,int x,int y,int z) // 函式的目的是把x柱的n個盤子,藉助y柱,移到z柱

而在遞迴時,柱子改變了,例如

move(n-1,x,z,y); // 這是把x柱的n-1個盤子,借組z柱,移到y柱

在進入遞迴時,盤子數量減少了,實際的柱子也改變了。

2樓:

n==1 一個盤子,直接從x移到z。n>1 先把上面n-1個盤子從x移到y,再把x最下面那個盤子移到z,再把y上的n-1個盤子移到z

3樓:小呆vs小笨

用個簡單的例子,斐波那契數列,已知f(1)=1,f(2)=1。又知f(3)=f(2)+f(1),f(4)=f(3)+f(2)即f(n)=f(n-1)+f(n-2),那我要求f(10)怎麼辦?那我就回溯f(10)=f(9)+f(8),但我f(9)不知道,再回溯f(9)=f(8)+f(7),我f(8)也不知道,那再回溯f(8)=f(7)+f(6)一直回溯到f(3)=f(2)+f(1),這時候f(1)和f(2)已知,我就可以遞迴求出f(3),f(4),f(5)·····f(10),問題就解決了

漢諾塔遞迴函式問題

4樓:

遞迴其實很簡單,你只要曉得啥子是巢狀呼叫就可以了,所謂巢狀呼叫,就是在一個函式裡呼叫另一個函式,main函式不能被呼叫的,所以遞迴就是有限次的巢狀呼叫本身函式,每次呼叫,系統都會重新分配記憶體,返回時就返回上次呼叫他的那塊記憶體中的呼叫函式處,這樣理解應該很簡單了

void move(int , char ,char,char); /*宣告函式,告訴系統我隨後要定義一個函式,他不對其中引數進行檢查,所以可以省略引數,一般只寫型別,表示有多少個什麼型別的引數,便於自己理解 */

main()

/*函式呼叫,用a,b,c代表3跟柱子,把盤子數,柱子**傳給函式*/

void move(int m, char p, char q, char r) //定義函式

else

getch();}

這裡面的遞迴涉及一個漢諾塔的演算法問題,具體講明白的話有點麻煩,總體思路是假設盤子全在a柱上,想放到c上

第n個人就想要是有人搬動其他n-1個盤子到b,那他只要搬一次從a到c就可以,在讓那個人把n-1個盤子放到c上

第n-1那個人就想要是有人搬動其他n-2個盤子到c,他只要搬動一次從a到b就可以,在讓那個人把n-2個盤子放到b上

....

第1個人就直接把盤子從a到c

這樣形成遞迴

我在倆處呼叫標記了a,b,我寫出步躊,你看看.

假設3個盤子

a函式相當於雙重迴圈中的外層迴圈

b函式相當於雙重迴圈中的內層迴圈

1,主函式呼叫,p=a,q=b,r=c,m=3,執行a,呼叫本身(a第一次呼叫)傳入p,r,q(a,c,b) 注意呼叫函式中p,r,q排列

2,被調函式是用p,q,r的順序接收傳入的p,r,q.p=a,q=c,r=b,m=2,執行a,呼叫本身(a第二次呼叫) 呼叫傳入p,r,q(a,b,c)

3,p=a,q=b,r=c,m=1,執行if,輸出a->c,返回a第二次呼叫

4,本次函式中p=a,q=c,r=b,m=2,向下執行,輸出a->b,執行b,呼叫本身(b第一次呼叫),傳入q,p,r(c,a,b),m=1

5,p=c,q=a,r=b,m=1,執行if,輸出c->b,返回b第一次呼叫

6,向下執行,執行完畢,返回a第一次呼叫

7,本次函式中p=a,q=b,r=c,m=3,向下執行,輸出a->c,執行b,呼叫本身(b第一次呼叫),傳入q,p,r(b,a,c),m=2

8,p=b,q=a,r=c,m=2,執行a,呼叫本身(a'第一次呼叫,注意是b函式呼叫中再次呼叫a) 傳入p,r,q(b,c,a)

9,p=b,q=c,r=a,m=1,執行if,輸出b->a,返回a'第一次呼叫

10,本次函式中p=b,q=a,r=c,m=2向下執行,輸出b->c,執行b,呼叫本身(b'的第一次呼叫,注意是b函式中再次呼叫b) 傳入q,p,r(a,b,c),m=1

11,p=a,q=b,r=c,m=1,執行if,輸出a->c返回b'第一次呼叫

12,向下執行,執行完畢,返回b第一次呼叫

13,向下執行,執行完畢,返回主函式

仔細分析每次呼叫時當前變數p,q,r中所代表的a,b,c,每次呼叫時,p,q,r都是新的變數

我看了你的問題,估計你把呼叫函式中的p,q,r變數與被調函式中p,q,r變數搞混了

/* 4,向下執行,執行b,呼叫本身(b第一次呼叫),由於本次函式中p=a,q=c,r=b,m=2,先輸出a->b,再傳入q=c,p=a,r=b,m=1

這裡不是[4] move 3# from a to c嗎

*/ 注意呼叫傳入的順序是q,p,r,傳入的值是c,a,b的順序,被調函式中是拿p,q,r的順序在接收,所以被調函式中值的順序就該是p=c,q=a,r=b,執行if就輸出c->b

不要想太複雜了,q,p,r是變數,用來儲存值的,而他只是個區域性變數,每次呼叫函式後給q,p,r新分配的記憶體地址不一樣。比如本次函式中q,p,r中放的值分別是q=c,p=a,r=b,當執行呼叫函式時,給被調函式傳入的是變數的值,也就是說實際上傳入的是c,a,b

在被調函式中,p,q,r是新的區域性變數,他接收來自呼叫函式中的值,行參接收值的順序與實參傳入值的順序是相對應的,因為實參傳入的順序是c,a,b,在行參接收值時也以這樣的順序接收,而行參變數的順序是p,q,r,所以被調函式中p=c,q=a,r=b

5樓:

void move(int , char ,char,char); 作為宣告的時候可以不加上變數名的。編譯器只需要知道有幾個引數,都是什麼型別的就足夠了。

但是在實現的時候必須加上。

6樓:匿名使用者

首先,不要試圖理解遞迴是怎樣執行的,這是一個很複雜的過程,把一個遞迴程式轉化為非遞迴的,往往需要耗費很多力氣。

再來講這個程式,如果要將n個盤子從a經過b轉移到c上,可以劃分為三個較小的過程,把n-1個盤子從a經過c轉移到b上,把第n個盤子從a轉移到c上,再把n-1個盤子從b經過a轉移到c上……如此細分下去,總可以完全劃分為2^n-1個小步(具體可由等比數列的求和算得)。

最基本的一點,遞迴的思想就是將大問題化為稍小的問題,而漢諾塔問題正是這一特徵的典型表現。

7樓:匿名使用者

簡單說就是當a柱子有n個盤子的時候,將n-1個移到b上,將剩下的那個移到c上再將n-1個移到c以做到將n個都移到c上,那麼,如何將n-1個盤子從a移到b呢?答案就是將(n-1)-1個盤子移到c上,再將剩下的那個移到b上.從b到c也是一樣的道理.

move(m-1,p,r,q),move(m-1,q,p,r)這兩句就是說把那n-1個盤子從a移到b再從b移到c.

因為原本的move(m-1,p,q,r)需要做的是將a的全部移到c,因此move(m-1,p,r,q)說的就是將a的全部移到b上(q,r位置互換說明了目標c換成b了).move(m-1,q,p,r)則說的是把b上的全部移到c上去了.

而在將a移到b這一步中,又可以分成將(n-1)-1個移到c,再將最後的那個移到b,再將(n-1)-1個移到b,如此不斷進行下去直到只剩1個的時候.這樣就形成了一個recursion,一直不斷重複相同的事情,僅僅是更換了柱子的順序.而需要移動的盤子的數量則不斷減少了.

漢諾塔遞迴演算法分析,求漢諾塔遞迴全過程的演算法詳解圖,記得一定要是圖釋哦!!!

我之前回答過的,http zhidao.baidu.hanoi塔問題,演算法分析如下,設a上有n個盤子。如果n 1,則將圓盤從a直接移動到c。如果n 2,則 1 將a上的n 1 等於1 個圓盤移到b上 2 再將a上的一個圓盤移到c上 3 最後將b上的n 1 等於1 個圓盤移到c上。如果n 3,則 a...

c語言遞迴呼叫漢諾塔,C語言函式遞迴呼叫漢諾塔問題

遞迴演算法的出發點不是由初始條件出發,而是把出發點放在求解的目標上,從所求的未知項出發逐次呼叫本身的求解過程,直到遞迴的邊界 即初始條件 漢諾塔問題的重點是分析移動的規則,找到規律和邊界條件。若需要將n個盤子從a移動到c就需要 1 將n 1個盤子從a移動到b 2 將你第n個從a移動到c 3 將n 1...

塔羅牌和多米諾骨牌的介紹,多米諾骨牌和塔羅牌是什麼東東?

塔羅牌的 是一種神祕,我們不確定十五世紀在義大利使用的塔羅牌是一種普遍的塔羅牌遊戲。那些有錢的贊助者要求漂亮的塔羅牌,有些牌就此流傳下來。此後沒多久,一副visconti sforza在1450年被設計出來,是最早最完整的塔羅牌之一。後來在十八十九世紀,塔羅牌被一群有影響力的學者所發現。這些人著迷於...