1. 程式人生 > 其它 >分治演算法解決漢諾塔問題

分治演算法解決漢諾塔問題

技術標籤:演算法與資料結構分治演算法漢諾塔遞迴遞迴法

一、漢諾塔問題概述

漢諾塔問題是一個古老而又有趣的問題。這個問題的具體內容是:將所有盤子從最左邊的塔 A 都移動到最右邊的塔 C 上。每次只能移動一個盤子,大的盤子不能壓在小的盤子上。

在這裡插入圖片描述

二、思路分析

我們先分別來看看只有一個、兩個、三個盤子的情況下,移動過程是怎樣的。

  • 一個盤子

    在這裡插入圖片描述

    如上圖所示,一個盤子的移動過程為:
    A → C A→C AC

  • 兩個盤子

    在這裡插入圖片描述
    如上圖所示,兩個盤子的移動過程為:


A → B A → C B → C A→B\\ A→C\\ B→C ABACBC

  • 三個盤子

    在這裡插入圖片描述

    如上所示,三個盤子的移動過程為:

    A → C A → B C → B A → C B → A B → C A → C A→C \\ A→B \\ C→B \\ A→C \\ B→A \\ B→C \\ A→C \\ ACABCBACBABCAC

從它們的移動過程,我們分析如下:

當只有一個盤子時,盤子直接 A→C,過程非常簡單。

當有兩個盤子時,我們會首先把上面的盤子 A→B,然後把最底下的盤子 A→C,最後把上面的盤子 B→C

當有三個盤子時,我們可把最下面的一個盤子看作一部分,上面的兩個盤子看作另一部分,則相當於首先把上面一部分的盤子 A→B,然後把最下面的盤子 A→C,最後把上面一部分的盤子 B→C

推廣到 N 個盤子時,我們可以將最下面的一個盤子看作單獨一部分,上面的 N-1 個盤子看作另外一部分。移動的思路可以概括為首先把上面 N-1 個盤子 A→B,然後把最下面的盤子 A→C,最後把上面 N-1 個盤子 B→C

那麼 N-1 個盤子是如何從塔 A 移動到塔 B 的呢?我們按照上面的思想,把 N-1 個盤子的最下面的盤子看作單獨一部分,上面的 N-2 個盤子看作另一部分,首先把上面 N-2 個盤子 A→C,然後把最下面的盤子 A→B,最後把上面 N-2 個盤子 C→B

接下來就是 N-2 個盤子的移動問題,依然是按照上面的思想…,直至分解到一個盤子的移動問題

從上面的分析流程我們可以看到,解決漢諾塔問題的核心思想就是分治思想

三、程式碼實現

/**
 * 分治思想解決漢諾塔問題 
 */
public static void hanoitower(int num, char a, char b, char c){
    if (num == 1){
        System.out.println(a + "->" + c);   // 只有一個盤子,直接 A->C 即可
    }else{
        hanoitower(num-1, a, c, b); // 把上面的 num-1 個盤子 A->B
        System.out.println(a + "->" + c);   // 把最下面的一個盤子 A->C
        hanoitower(num-1, b, a, c); // 再把上面 num-1 個盤子 B->C
    }
}