日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

汉诺塔问题(分治+源码+动画演示)

發(fā)布時(shí)間:2024/5/8 编程问答 60 豆豆
生活随笔 收集整理的這篇文章主要介紹了 汉诺塔问题(分治+源码+动画演示) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

漢諾塔問題(分治+源碼+動(dòng)畫演示)

漢諾塔問題源自印度一個(gè)古老的傳說,印度教的“創(chuàng)造之神”梵天創(chuàng)造世界時(shí)做了 3 根金剛石柱,其中的一根柱子上按照從小到大的順序摞著 64 個(gè)黃金圓盤。梵天命令一個(gè)叫婆羅門的門徒將所有的圓盤移動(dòng)到另一個(gè)柱子上,移動(dòng)過程中必須遵守以下規(guī)則:

每次只能移動(dòng)柱子最頂端的一個(gè)圓盤;

每個(gè)柱子上,小圓盤永遠(yuǎn)要位于大圓盤之上;

圖 1 給您展示了包含 3 個(gè)圓盤的漢諾塔問題:

圖 1 漢諾塔問題

一根柱子上摞著 3 個(gè)不同大小的圓盤,那么在不違反規(guī)則的前提下,如何將它們移動(dòng)到另一個(gè)柱子上呢?圖 2 給大家提供了一種實(shí)現(xiàn)方案:

圖 2 漢諾塔問題的解決方案

漢諾塔問題中,3 個(gè)圓盤至少需要移動(dòng) 7 次,移動(dòng) n 的圓盤至少需要操作 2n-1 次。

在漢諾塔問題中,當(dāng)圓盤個(gè)數(shù)不大于 3 時(shí),多數(shù)人都可以輕松想到移動(dòng)方案,隨著圓盤數(shù)量的增多,漢諾塔問題會(huì)越來越難。也就是說,圓盤的個(gè)數(shù)直接決定了漢諾塔問題的難度,解決這樣的問題可以嘗試用分治算法,將移動(dòng)多個(gè)圓盤的問題分解成多個(gè)移動(dòng)少量圓盤的小問題,這些小問題很容易解決,從而可以找到整個(gè)問題的解決方案。

分治算法解決漢諾塔問題

為了方便講解,我們將 3 個(gè)柱子分別命名為起始柱、目標(biāo)柱和輔助柱。實(shí)際上,解決漢諾塔問題是有規(guī)律可循的:

  • 當(dāng)起始柱上只有 1 個(gè)圓盤時(shí),我們可以很輕易地將它移動(dòng)到目標(biāo)柱上;

  • 當(dāng)起始柱上有 2 個(gè)圓盤時(shí),移動(dòng)過程如下圖所示:

  • 圖 3 移動(dòng)兩個(gè)圓盤

    移動(dòng)過程是:先將起始柱上的 1 個(gè)圓盤移動(dòng)到輔助柱上,然后將起始柱上遺留的圓盤移動(dòng)到目標(biāo)柱上,最后將輔助柱上的圓盤移動(dòng)到目標(biāo)柱上。

  • 當(dāng)起始柱上有 3 個(gè)圓盤時(shí),移動(dòng)過程如圖 2 所示,仔細(xì)觀察會(huì)發(fā)現(xiàn),移動(dòng)過程和 2 個(gè)圓盤的情況類似:先將起始柱上的 2 個(gè)圓盤移動(dòng)到輔助柱上,然后將起始柱上遺留的圓盤移動(dòng)到目標(biāo)柱上,最后將輔助柱上的圓盤移動(dòng)到目標(biāo)柱上。
  • 通過分析以上 3 種情況的移動(dòng)思路,可以總結(jié)出一個(gè)規(guī)律:對(duì)于 n 個(gè)圓盤的漢諾塔問題,移動(dòng)圓盤的過程是:

    將起始柱上的 n-1 個(gè)圓盤移動(dòng)到輔助柱上;

    將起始柱上遺留的 1 個(gè)圓盤移動(dòng)到目標(biāo)柱上;

    將輔助柱上的所有圓盤移動(dòng)到目標(biāo)柱上。

    由此,n 個(gè)圓盤的漢諾塔問題就簡(jiǎn)化成了 n-1 個(gè)圓盤的漢諾塔問題。按照同樣的思路,n-1 個(gè)圓盤的漢諾塔問題還可以繼續(xù)簡(jiǎn)化,直至簡(jiǎn)化為移動(dòng) 3 個(gè)甚至更少圓盤的漢諾塔問題。

    如下為分治算法解決漢諾塔問題的偽代碼:

    // num 表示移動(dòng)圓盤的數(shù)量,source、target、auxiliary 分別表示起始柱、目標(biāo)柱和輔助柱 hanoi(num ,
    source , target , auxiliary):
    if num == 1: // 如果圓盤數(shù)量?jī)H有 1 個(gè),則直接從起始柱移動(dòng)到目標(biāo)柱
    print(從 source 移動(dòng)到 target)
    else:
    // 遞歸調(diào)用 hanoi 函數(shù),將 num-1 個(gè)圓盤從起始柱移動(dòng)到輔助柱上,整個(gè)過程的實(shí)現(xiàn)可以借助目標(biāo)柱
    hanoi(num-1 , source , auxiliary , target)
    // 將起始柱上剩余的最后一個(gè)大圓盤移動(dòng)到目標(biāo)柱上
    print(從 source 移動(dòng)到 target)
    // 遞歸調(diào)用 hanoi 函數(shù),將輔助柱上的 num-1 圓盤移動(dòng)到目標(biāo)柱上,整個(gè)過程的實(shí)現(xiàn)可以借助起始柱
    hanoi(n-1 , auxiliary , target , source)

    漢諾塔問題的代碼實(shí)現(xiàn)

    根據(jù)偽代碼,我們?yōu)榇蠹揖帉懞昧讼鄳?yīng)的 C 語言、Java 以及 Python 程序。

    如下是解決漢諾塔問題的 C 語言程序:

    #include <stdio.h> void hanoi(int num, char sou, char tar,char aux) {//統(tǒng)計(jì)移動(dòng)次數(shù)static int i = 1;//如果圓盤數(shù)量?jī)H有 1 個(gè),則直接從起始柱移動(dòng)到目標(biāo)柱if (num == 1) {printf("第%d次:從 %c 移動(dòng)至 %c\n", i, sou, tar);i++;}else {//遞歸調(diào)用 hanoi() 函數(shù),將 num-1 個(gè)圓盤從起始柱移動(dòng)到輔助柱上hanoi(num - 1, sou, aux, tar);//將起始柱上剩余的最后一個(gè)大圓盤移動(dòng)到目標(biāo)柱上printf("第%d次:從 %c 移動(dòng)至 %c\n", i, sou, tar);i++;//遞歸調(diào)用 hanoi() 函數(shù),將輔助柱上的 num-1 圓盤移動(dòng)到目標(biāo)柱上hanoi(num - 1, aux, tar, sou);} } int main() {//以移動(dòng) 3 個(gè)圓盤為例,起始柱、目標(biāo)柱、輔助柱分別用 A、B、C 表示hanoi(3, 'A', 'B', 'C');return 0; }

    如下是解決漢諾塔問題的 Java 程序:

    public class Demo {// 統(tǒng)計(jì)移動(dòng)次數(shù)public static int i = 1;public static void hanoi(int num, char sou, char tar, char sux) {// 如果圓盤數(shù)量?jī)H有 1 個(gè),則直接從起始柱移動(dòng)到目標(biāo)柱if (num == 1) {System.out.println("第" + i + "次:從" + sou + "移動(dòng)到" + tar);i++;} else {// 遞歸調(diào)用 hanoi() 函數(shù),將 num-1 個(gè)圓盤從起始柱移動(dòng)到輔助柱上hanoi(num - 1, sou, sux, tar);// 將起始柱上剩余的最后一個(gè)大圓盤移動(dòng)到目標(biāo)柱上System.out.println("第" + i + "次:從" + sou + "移動(dòng)到" + tar);i++;// 遞歸調(diào)用 hanoi() 函數(shù),將輔助柱上的 num-1 圓盤移動(dòng)到目標(biāo)柱上hanoi(num - 1, sux, tar, sou);}}public static void main(String[] args) {// 以移動(dòng) 3 個(gè)圓盤為例,起始柱、目標(biāo)柱、輔助柱分別用 A、B、C 表示hanoi(3, 'A', 'B', 'C');} }

    如下是解決漢諾塔問題的 Python 程序:

    #記錄移動(dòng)次數(shù) i = 1 def hanoi(num,sou,tar,aux):global iif num==1:print("第%d次:從 %c 移動(dòng)至 %c" % (i, sou, tar))i=i+1else:#遞歸調(diào)用 hanoi() 函數(shù),將 num-1 個(gè)圓盤從起始柱移動(dòng)到輔助柱上hanoi(num - 1, sou, aux, tar)#將起始柱上剩余的最后一個(gè)大圓盤移動(dòng)到目標(biāo)柱上print("第%d次:從 %c 移動(dòng)至 %c" % (i, sou, tar))i=i+1#遞歸調(diào)用 hanoi() 函數(shù),將輔助柱上的 num-1 圓盤移動(dòng)到目標(biāo)柱上hanoi(num - 1, aux, tar, sou) #以移動(dòng) 3 個(gè)圓盤為例,起始柱、目標(biāo)柱、輔助柱分別用 A、B、C 表示 hanoi(3, 'A', 'B', 'C');

    以上程序的執(zhí)行結(jié)果均為:

    第1次:從 A 移動(dòng)至 B
    第2次:從 A 移動(dòng)至 C
    第3次:從 B 移動(dòng)至 C
    第4次:從 A 移動(dòng)至 B
    第5次:從 C 移動(dòng)至 A
    第6次:從 C 移動(dòng)至 B
    第7次:從 A 移動(dòng)至 B

    總結(jié)

    以上是生活随笔為你收集整理的汉诺塔问题(分治+源码+动画演示)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。