首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 遞迴解決漢諾塔問題完整教學:算法推導、代碼實現、複雜度分析與變體擴展

     編輯:Java 相關知識

漢諾塔問題描述

經典數學遊戲:三根柱子 A、B、C。A 柱自下而上疊放 n 個直徑遞減的圓盤。目標:將所有圓盤移動到 C 柱,規則:

  1. 每次只能移動一個圓盤
  2. 大圓盤不能疊在小圓盤上
  3. 可借助 B 柱作為中轉

遞迴思想推導

設 move(n, from, to, aux) 表示將 n 個圓盤從 from 移到 to,借助 aux。

  1. 基例:n=1,直接移動 from → to
  2. 遞迴步驟(n>1):
    1. 將頂部 n-1 個圓盤從 from 移到 aux(借助 to)
    2. 將第 n 個(最大)圓盤從 from 移到 to
    3. 將 n-1 個圓盤從 aux 移到 to(借助 from)

Java 完整實現


public class HanoiTower {
    private static int step = 0;
    
    public static void main(String[] args) {
        int n = 3; // 圓盤數
        System.out.println("=== 漢諾塔 " + n + " 層移動步驟 ===");
        move(n, 'A', 'C', 'B');
        System.out.println("總步數:" + step + " (理論最少 2^n-1 = " + ((1<

執行輸出示例 (n=3)

=== 漢諾塔 3 層移動步驟 ===
第 1 步:圓盤 1 從 A 移動到 C
第 2 步:圓盤 2 從 A 移動到 B
第 3 步:圓盤 1 從 C 移動到 B
第 4 步:圓盤 3 從 A 移動到 C
第 5 步:圓盤 1 從 B 移動到 A
第 6 步:圓盤 2 從 B 移動到 C
第 7 步:圓盤 1 從 A 移動到 C
總步數:7 (理論最少 2^n-1 = 7)

遞迴調用樹圖解 (n=3)

move(3, A, C, B)
├─ move(2, A, B, C)
│  ├─ move(1, A, C, B) → 1:A→C
│  ├─ 2:A→B
│  └─ move(1, C, B, A) → 1:C→B
├─ 3:A→C
└─ move(2, B, C, A)
   ├─ move(1, B, A, C) → 1:B→A
   ├─ 2:B→C
   └─ move(1, A, C, B) → 1:A→C

複雜度分析

指標複雜度說明
時間複雜度O(2^n)遞迴關係 T(n) = 2T(n-1) + 1,解得 T(n) = 2^n - 1
空間複雜度O(n)遞迴調用棧最大深度 n
最優解步數2^n - 1證明:每個圓盤至少移動一次,最大圓盤移動 1 次,其餘各移動 2 次

非遞迭實現(棧模擬遞迴)


public static void moveIterative(int n, char from, char to, char aux) {
    // 任務幀:n, from, to, aux, state(0=開始,1=步驟1完成,2=步驟2完成)
    class Frame { int n; char f,t,a; int state; }
    Deque stack = new ArrayDeque<>();
    stack.push(new Frame(n, from, to, aux, 0));
    
    while (!stack.isEmpty()) {
        Frame cur = stack.peek();
        if (cur.n == 1) {
            System.out.println("移動圓盤 1 從 " + cur.f + " 到 " + cur.t);
            stack.pop();
            continue;
        }
        switch (cur.state) {
            case 0: // 執行步驟1:move(n-1, from, aux, to)
                cur.state = 1;
                stack.push(new Frame(cur.n-1, cur.f, cur.a, cur.t, 0));
                break;
            case 1: // 執行步驟2:移動第 n 個
                System.out.println("移動圓盤 " + cur.n + " 從 " + cur.f + " 到 " + cur.t);
                cur.state = 2;
                break;
            case 2: // 執行步驟3:move(n-1, aux, to, from)
                cur.state = 3;
                stack.push(new Frame(cur.n-1, cur.a, cur.t, cur.f, 0));
                break;
            default: // 完成
                stack.pop();
        }
    }
}

經典變體擴展

變體規則變化解法思路
四柱漢諾塔增加 D 柱Frame-Stewart 算法:分成 k 和 n-k 兩組,最優 k 尚無通用公式
循環漢諾塔柱子排成環,只能順/逆時針移動移動次數 3^n - 1,遞迴關係變化
雙色漢諾塔圓盤黑白交替,同色不可疊放狀態空間擴大,需 BFS/A* 搜索
可重複圓盤允許相同大小圓盤狀態表示增加計數器,動態規劃

教學應用場景

  • 遞迴入門:最經典的「分治+遞迴」教學案例
  • 棧原理:展示函數調用棧如何模擬遞迴
  • 指數增長直觀體驗:n=20 時步數超百萬,n=64 步數 1.8×10^19(傳說世界末日)
  • 算法優化思維:遞迴→迭代→備忘錄→數學公式直接計算

總結

漢諾塔是理解遞迴分治、問題分解、狀態轉移的最佳模型。核心洞見:「將大問題分解為相同結構的小問題,信任遞迴調用能正確解決子問題,專注於當前層級的組合邏輯」。這種思維是掌握動態規劃、回溯、分治算法的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved