1. 程式人生 > >《資料結構和演算法》之漢諾塔

《資料結構和演算法》之漢諾塔

一,問題描述:

       法國數學家愛德華·盧卡斯曾編寫過一個印度的古老傳說:在世界中心貝拿勒斯(在印度北部)的聖廟裡,一塊黃銅板上插著三根寶石針。印度教的主神梵天在創造世界的時候,在其中一根針上從下到上地穿好了由大到小的64片金片,這就是所謂的漢諾塔。不論白天黑夜,總有一個僧侶在按照下面的法則移動這些金片:一次只移動一片,不管在哪根針上,小片必須在大片上面。僧侶們預言,當所有的金片都從梵天穿好的那根針上移到另外一根針上時,世界就將在一聲霹靂中消滅,而梵塔、廟宇和眾生也都將同歸於盡。

    不管這個傳說的可信度有多大,如果考慮一下把64片金片,由一根針上移到另一根針上,並且始終保持上小下大的順序。這需要多少次移動呢?這裡需要遞迴的方法。假設有n片,移動次數是f(n).顯然f(1)=1,f(2)=3,f(3)=7,且f(k+1)=2*f(k)+1。此後不難證明f(n)=2^n-1。n=64時,假如每秒鐘一次,共需多長時間呢?一個平年365天有31536000 秒,閏年366天有31622400秒,平均每年31556952秒,計算一下:18446744073709551615秒。這表明移完這些金片需要5845.54億年以上,而地球存在至今不過45億年,太陽系的預期壽命據說也就是數百億年。真的過了5845.54億年,不說太陽系和銀河系,至少地球上的一切生命,連同梵塔、廟宇等,都早已經灰飛煙滅。

                                                         

                                                                                                                     圖1  模擬圖

二,問題分析

      1,分解問題

      在這個問題中,我們發現由於每次只能移動一個圓盤,所以在移動的過程中顯然要藉助另外一根針才行。也就是說第1步將1到63個盤子藉助Z移動到Y上,第3步將Y針上的63個盤子藉助X移動到Z針上。那麼我們把所有新的思路聚集為以下兩個問題:

       問題一:將X上的63個盤子藉助Z移動到Y上;

       問題二:將Y上的63個盤子藉助X移動到Z上。

      2,分解解答

      問題一的圓盤移動步驟為:

      (1)先將前62個盤子移動到Z上,確保大盤在在小盤下

      (2)再將最底下的第63個盤子移動到Y上

      (3)最後將Z上的62個盤子移動到Y上

       問題二的圓盤移動步驟:

      (1)先將前62個盤子移動到X上,確保大盤在小盤下

       (2)再將最底下的63個盤子移動到Z上

       (3)最後將X上的62個盤子移動到Y上。

三,程式碼分析

#include <stdio.h>

void move(int n, char x, char y, char z)
{
    if( 1 == n)
    {
        printf("%c-->%c\n", x,z);
    }
    else
    {
        move(n-1,x,z,y);            //將n-1個盤子從x藉助z移動到y上面
        printf("%c-->%c\n",x,z);    //將第n個盤子從x上移動到z上
        move(n-1,y,x,z);            //將n-1個盤子從u上藉助x移動到z上
    }
}
int main()
{
    int n;

    printf("請輸入漢諾塔的層數:\n");
    scanf("%d",&n);
    printf("移動的步驟如下:\n");
    move(n,'x','y','z');

    return 0;
}

         在上面的程式碼中可以看到其中使用了遞迴的思想,不斷地呼叫move函式則最終可以說實現移動的效果。當n=3時的結果為圖2結果圖所示,有移動的步驟。