1. 程式人生 > >資料結構經典演算法學習之河內之塔(漢諾塔)

資料結構經典演算法學習之河內之塔(漢諾塔)

河內之塔 (漢諾塔)


故事背景:河內之塔(Towers of Hanoi)是法國人M.Claus(Lucas)於1883年從泰國帶至法國的,河內為越戰時北越的首都,即現在的胡志明市;1883年法國數學家 Edouard Lucas曾提及這個故事,據說創世紀時Benares有一座波羅教塔,是由三支鑽石棒(Pag)所支撐,開始時神在第一根棒上放置64個由上至下依由小至大排列的金盤(Disc),並命令僧侶將所有的金盤從第一根石棒移至第三根石棒,且搬運過程中遵守大盤子在小盤子之下的原則,若每日僅搬一個盤子,則當盤子全數搬運完畢之時,此塔將毀損,而也就是世界末日來臨之時。

問題描述
有一個梵塔,塔內有三個座A、B、C,A座上有諾幹個盤子,盤子大小不等,大的在下,小的在上(如圖)。
把這些個盤子從A座移到C座,中間可以借用B座但每次只能允許移動一個盤子,並且在移動過程中,3個座上的盤子始終保持大盤在下,小盤在上。
描述簡化:

把A柱上的n個盤子移動到C柱,其中可以借用B柱。

問題手拆

設定有n個盤子在A上

則:當n=1,A——>C

        當n=2,A——>B,A——>C,B——>C

        當n=3,A——>C,A——>B,C——>B,A——C,B——>A,B——C,A——>C

        當n=4,A——>B,A——>C,B——>C,A——B,C——>A,C——B,A——>B(至此將頂部3個盤子都移到了B上),A——>C,B——>C,B——>A,C——A,B——>C,A——B,A——>C,B——>C

        當n=5,A——>C,A——>B,C——>B,A——C,B——>A,B——C,A——>C(至此將頂部3個盤子都移到了C上),A——>B,C——>B,C——>A,B——A,C——>B,A——C,A——>B,C——>B(至此將頂部4個盤子都移到了B上),A——>C(這裡博主就不往下面寫了,交給讀者們吧,我腦子有點累。。。思路:此時B上有4個盤子,C上有一個最大的盤子,假設將C上的盤子忽略掉存在,因為它已經是最大的了,上面放任何一個盤子都不會違反規則;至此將B的情景放在上面n=4的那一步中,假設B就是A,那麼繼續進行,將B的最大盤子放到C上;至此再類推到第二步n=3時...)...........

        當n=....

問題思考

其實上面的問題,大家經過思考會發現,不管過程如何曲折,想要把A上n個盤子移到C上,就必須要把前n-1個盤子先放到B上,然後將最大的盤子放到C上;之後再將C上的固定了的盤子假設不存在,此刻B上的盤子當做上一步的A盤子,繼續一樣的思路進行(其實仔細看上面的問題手拆,會發現規律,前幾步都是重複的,後幾步其實只是把A換成了B或者A換成了C)。另外可能網上許多的類似關於漢諾塔的解釋方法,都沒有詳細多少如何把n-1個盤子放到B上呢?其實給大家提供一個解決思路:想要將n-1個盤子放到B上,那就必須先將n-2個盤子移到C處,再將最大的盤子從A移到B處。其實說白了仍然是漢諾塔的遞迴)

程式碼實現(網上有很多一樣的大致實現,但都是一個思路的實現,具體到函式層的實現並沒有寫,博主這裡有時間給大家寫一個做參考,暫時先放個雷同的吧)

public void hanoi(String A, String B, String C, int n) {
		if (n == 1) {
			System.out.println("這個簡單,直接將" + A +"的"+n+"個盤子移動到" + C + "!");
		} else {
			hanoi(A, C, B, n - 1);
			System.out.println("將" + A +"的"+n+"個盤子移動到" + C + "!");
			hanoi(B, A, C, n - 1);

		}

	}