Java實現漢諾塔算法

一、什麼是漢諾塔?

漢諾塔是一種數學問題,同時也是一種益智遊戲。其規則如下:

將所有的盤子從起點柱子移動到目標柱子,每次只能移動一個盤子,並且大盤子不能放在小盤子上面。起始柱子上的盤子按大小順序由下到上依次編號為1至n,目標柱子上無盤子。

二、算法思路

假設有三個柱子分別為A、B、C,現在要從A柱子上將n個盤子移至C柱子,那麼漢諾塔算法的解題步驟如下:

Step1: 將A柱子上編號為1至n-1的盤子移動至B柱子,此時空出A柱子的最底下一個盤子。

Step2: 將A柱子上編號為n的盤子移動至C柱子,此時A柱子上無盤子。

Step3: 將B柱子上編號為1至n-1的盤子移動至C柱子,此時漢諾塔遊戲成功結束。

以上便是漢諾塔問題求解的遞歸思路。接下來,我們將這個思路用Java語言實現。

三、Java代碼實現

public class HanoiTower {
    public static void hanoi(int n, char A, char B, char C) {
        if (n == 1) {//遞歸出口:只有一個盤子的情況
            System.out.println(A + "->" + C);
            return;
        }
        hanoi(n - 1, A, C, B);//Step1
        System.out.println(A + "->" + C);//Step2
        hanoi(n - 1, B, A, C);//Step3
    }
    public static void main(String[] args) {
        int n = 3;//漢諾塔的盤子數量
        hanoi(n, 'A', 'B', 'C');
    }
}

四、程序演示

運行上述代碼,可以得到如下輸出結果:

A->C

A->B

C->B

A->C

B->A

B->C

A->C


五、優化思路

當盤子數較大時,遞歸代碼的執行效率較低。為了提高程序的效率,可以使用非遞歸方式實現漢諾塔算法。具體方法為:

Step1: 直接將A柱子上編號為1至n的盤子移動至C柱子,此時A柱子上無盤子,B柱子是備用柱子。

Step2: 當n為奇數時,將B柱子作為中間柱子,依次將C柱子上編號為1至n的奇數盤子(從C柱子底部開始)移動至B柱子,再將A柱子上編號為1至n的偶數盤子依次移動至C柱子,最後將B柱子上的所有盤子依次移動至C柱子。當n為偶數時,將A柱子作為中間柱子,重複以上操作。

以上方法可以通過棧數據結構實現,具體實現方式可參考下方代碼:

import java.util.Stack;

public class HanoiTower {
    static Stack s1 = new Stack();//表示A柱子
    static Stack s2 = new Stack();//表示B柱子
    static Stack s3 = new Stack();//表示C柱子
    
    public static void main(String[] args) {
        int n = 3;//漢諾塔的盤子數量
        for (int i = n; i >= 1; i--) {
            s1.push(i);//向A柱子中壓入n個圓盤
        }
        hanoi(n);//移動n個盤子
    }

    public static void hanoi(int n) {
        int from = 1;//表示起始塔
        int to = 3;//表示目標塔
        if (n % 2 == 0) {
            to = 2;//當n為偶數時,將B柱子作為中間柱子
        }
        int mid = 6 - from - to;//表示中間塔
        int count = 0;//用於計數
        boolean isUp = true;//用於表示彈出的盤子是否向上
        while (s3.size() < n) {//當C柱子上的盤子數量不足n時
            if (isUp) {//彈出A或B柱子的棧頂元素向上
                int x;
                if (!s1.empty() && (s2.empty() || s1.peek() < s2.peek())) {
                    x = s1.pop();//從A柱子彈出元素
                    System.out.println("Move " + x + " from " + from + " to " + to);
                    s2.push(x);//將元素壓入B柱子
                    if (s3.size() == n) {//當圓盤全部移動到C柱子上時,退出循環
                        break;
                    }
                } else if (!s2.empty() && (s1.empty() || s2.peek() < s1.peek())) {
                    x = s2.pop();//從B柱子彈出元素
                    System.out.println("Move " + x + " from " + (from + 1) % 3 + " to " + to);
                    s1.push(x);//將元素壓入A柱子
                    if (s3.size() == n) {//當圓盤全部移動到C柱子上時,退出循環
                        break;
                    }
                }
                count++;//計數器加1
                if (count == n) {//當計數器值為n時,改變彈出元素的方向
                    isUp = false;
                }
            } else {//彈出C柱子的棧頂元素向下
                int x;
                if (!s1.empty() && (s3.empty() || s1.peek() < s3.peek())) {
                    x = s1.pop();//從A柱子彈出元素
                    System.out.println("Move " + x + " from " + from + " to " + mid);
                    s3.push(x);//將元素壓入C柱子
                } else if (!s3.empty() && (s1.empty() || s3.peek() < s1.peek())) {
                    x = s3.pop();//從C柱子彈出元素
                    System.out.println("Move " + x + " from " + to + " to " + from);
                    s1.push(x);//將元素壓入A柱子
                }
                count--;//計數器減1
            }
        }
    }
}

六、總結

漢諾塔算法作為一種數學問題和益智遊戲,可以啟發人們思考和鍛煉邏輯思維能力。在Java語言中,漢諾塔算法可以通過遞歸和非遞歸方式實現,並且非遞歸方式能夠有效提高程序的執行效率。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/250475.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-13 13:28
下一篇 2024-12-13 13:28

相關推薦

  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • 蝴蝶優化算法Python版

    蝴蝶優化算法是一種基於仿生學的優化算法,模仿自然界中的蝴蝶進行搜索。它可以應用於多個領域的優化問題,包括數學優化、工程問題、機器學習等。本文將從多個方面對蝴蝶優化算法Python版…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Bean加載過程

    Java Bean加載過程涉及到類加載器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean加載的過程。 一、類加載器 類加載器是Java虛擬機…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Python實現爬樓梯算法

    本文介紹使用Python實現爬樓梯算法,該算法用於計算一個人爬n級樓梯有多少種不同的方法。 有一樓梯,小明可以一次走一步、兩步或三步。請問小明爬上第 n 級樓梯有多少種不同的爬樓梯…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發布。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • AES加密解密算法的C語言實現

    AES(Advanced Encryption Standard)是一種對稱加密算法,可用於對數據進行加密和解密。在本篇文章中,我們將介紹C語言中如何實現AES算法,並對實現過程進…

    編程 2025-04-29
  • Java判斷字符串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字符串中是否存在多個指定字符: 一、字符串遍歷 字符串是Java編程中非常重要的一種數據類型。要判斷字符串中是否存在多個指定字符…

    編程 2025-04-29

發表回復

登錄後才能評論