1. 程式人生 > >數據結構(二)棧與隊列---遞歸之漢羅塔

數據結構(二)棧與隊列---遞歸之漢羅塔

隊列 金剛 最終 想法 兩個 實現 ... 分享 命令

(一)漢羅塔的了解

大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。

(二)拆分小塊,分治思想

只有3個圓盤時

技術分享圖片

步驟一:將A柱上面的兩個礙事的放到B上

技術分享圖片

步驟二:將A柱上的唯一一個圓盤移動到目標C柱

技術分享圖片

步驟三:將B柱上的礙事的一個圓盤放入A柱

技術分享圖片

步驟四:將B柱上的唯一一個圓盤放入目標C柱

技術分享圖片

步驟五:將A柱子上的唯一一個圓盤放入目標C柱子中

技術分享圖片

步驟總結

Hanoi(n,A,B,C)將n個圓盤從A移動到C,經過B

最開始:需要移動的圓盤n都在A柱上
1.將A柱的礙事圓盤n-1個經過C,移動到B     Hanoi(n-1,A,C,B) 2.將A中唯一最大圓盤移動到C          move(n,A,C)
3.將B中的所有圓盤使用同樣的方法移動到C中   Hanoi(n-1,B,A,C) 一次操作,將所有需要移動的圓盤n
-1放到B柱上   同樣將 所有我們可以進行下一次遞歸了

(三)代碼實現

int count;

void move(int n, char q, char p)
{
    count++;
    printf("%d times Move %d: Move from %c to %c\n", count, n, q, p);
}

void Hanoi(int n, char a, char b, char c)  //函數定義:將n個圓盤,由柱a經過柱b移動到目標柱c { if (n == 1) move(n, a, c);  //若是只有一個圓盤,直接移動到目標柱中 else { Hanoi(n - 1, a, c, b);  //將a上面的n-1個圓盤經過c移動到b中 move(n, a, c);       //將剩下的一個最大圓盤從a移動到c Hanoi(n - 1, b, a, c);  //同樣的想法將b中的n-1個圓盤移動到c中 } }
int main() { int n = 3; Hanoi(n, ‘X, ‘Y, ‘Z); system("pause"); return 0; }
int main()
{
    int n = 3;
    Hanoi(n, X, Y, Z);

    system("pause");
    return 0;
}

技術分享圖片

int main()
{
    int n = 4;
    Hanoi(n, X, Y, Z);

    system("pause");
    return 0;
}

技術分享圖片

(四)解析

1.假設移動n個圓盤從A柱到B柱的次數為H(n)
2.先把n-1個盤子從A柱移動到B柱,則需要移動的次數為H(n-1)
3.再把最大的那個圓盤從A柱移動到C柱需要一次
4.再把n-1個圓盤從B柱移動到C柱需要H(n-1)
5.由此可以得出
當n=1時,H(1)=1;
當n>1時,H(n)=2*H(n-1)+1;
6.由5得出H(n)=2^n-1  (n>0)

(五)總結

遞歸寫起來簡單,想起來有點燒腦....
漢羅塔移動:
1.柱A中有n個圓盤需要移動到目標柱C中
2.將柱A上的n-1個圓盤移動到目標柱B中
3.將柱A中最後1個圓盤移動到目標柱C中
4.將柱B中的n-1個圓盤移動到目標柱C中
註:目標柱在函數中是會變的,不過我們調用的最終目標柱是C
由上面四個步驟可以知道,移動到目標柱的規律是一樣的。所以我們定義一個函數用來將所有需要移動的圓盤移動到目標柱上
void Hanoi(int n, char a, char b, char c)
現在使用函數來說明步驟
1.Hanoi(n, X, Y, Z);    將n個圓盤由a=X柱移動到c=Z柱
2.Hanoi(n - 1, a, c, b);      將柱A上的n-1個圓盤移動到目標柱B中
3.move(n, a, c);              將柱A中最後1個圓盤移動到目標柱C中
4.Hanoi(n - 1, b, a, c)       將柱B中的n-1個圓盤移動到目標柱C中
move(n, a, c); //是不是真正移動了某個圓盤,我們只是去打印出來

數據結構(二)棧與隊列---遞歸之漢羅塔