1. 程式人生 > 其它 >遞迴呼叫應用例項-漢諾塔

遞迴呼叫應用例項-漢諾塔

遞迴呼叫應用例項-漢諾塔

√漢諾塔傳說

漢諾塔:漢諾塔(又稱河內塔)問題是源於印度一個古老傳說的益智玩具。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。

假如每秒鐘移動一次,共需多長時間呢?移完這些金片需要5845.54億年以上,太陽系的預期壽命據說也就是數百億年。真的過了5845.54億年,地球上的一切生命,連同梵塔、廟宇等,都早已經灰飛煙滅

 

分析 :

在思考這個問題的時候 ,我們可以想 ,假設沒有那麼多的盤子 ,而是僅僅只有一大一小兩個盤子的話 ,這個操作就很簡單 ,首先將大的盤子移動到C的位置 ,小一點的盤子移動到B的位置(假設兩個盤子的位置都在A處) ,通過將兩個盤分開 ,之後再將小的盤子放到大盤子上就完成了所有的盤子的移動

既然2個盤子的情況十分簡單的話 ,那麼不妨將無論多少盤子都思考為 ,最下面一張盤為一張盤 ,上面的複數張盤子都是一張盤的思維方式 ,之後將上面所有的盤子移動到一個位置和最下面的盤子分開之後 ,在合到一起即可(也就是上面的所有盤子移動到B ,下面的移動到C ,再將上面的移動到C即完成了重合)

 

 

程式碼示例

public class HanoiTower {
  public static void main(String[] args) {
      Tower t1 = new Tower();
      t1.move(5,'A','B','C');
  }
}

class Tower {
  //num表示要移動的個數 a,b,c表示對應的塔
  public void move(int num, char a, char b, char c)
  {
      //如果只有一個盤 num = 1
      if (num == 1){
          System.out.println(a + "->" + c);
      }else {
          move(num - 1, a , c , b);
          //移動上面所有盤從a到b ,但是藉助c
          System.out.println(a + "->" + c);
          //把最下面的盤移動到c
          move(num - 1, b , a , c);
          //再把b塔的所有盤移動到c(藉助a塔)即可完成移動
      }

  }
}

程式碼分析 (這裡我們仍然使用了遞迴來解決這個問題)

class Tower
//這裡定義了一個漢諾塔類
public void move(int num, char a, char b, char c)
//這裡定義了一個move方法,由於是通過列印的方式將移動的過程展現出來,因此並沒有返回值
//傳入的三個引數分別為 想要檢視移動的盤子數量
//後面的三個字元引數分別對應三個塔
if (num == 1)
//判斷假設我們傳入的數量為1的話,那就沒有遞迴的必要
//直接將這一個盤子移動到C塔即可
else {
    move(num - 1, a , c , b);
    //移動上面所有盤從a到b ,但是藉助c
    System.out.println(a + "->" + c);
    //把最下面的盤移動到c
    move(num - 1, b , a , c);
    //再把b塔的所有盤移動到c(藉助a塔)即可完成移動
    }
//這裡的else就採用我們之前提出的方法,也就是將所有的盤子看成上面所有的盤子,下面最後的一個盤子
//將二者認定為兩個盤子來進行移動操作
move(num - 1, a , c , b);
//num-1表示除開下面一個盤子的剩餘盤子,a,c,b如程式碼下的註釋一致
//也就是將上面的-1的盤子遞迴移動到b塔中去,移動結束之後只剩下了最下面一個盤
System.out.println(a + "->" + c);
//移動a塔中剩餘的盤子到c塔
//此時三塔的情況就是剩餘的塔在b塔,最後一個盤子在c塔
move(num - 1, b , a , c);
//這個操作就是將b塔中的剩餘盤子移動到c塔的盤子上面即可完成移動的操作