Mr.J--HanioTower(遞迴演算法)
阿新 • • 發佈:2018-11-17
HanioTower(漢諾塔),資料結構高階遞迴中的經典問題,是每一個初學資料結構的同學必經之路,可能有的同學在學習C語言時候就已經遇見過這個問題。
漢諾塔的起源:相傳在古印度聖廟中,有一種被稱為漢諾塔(Hanoi)的遊戲。該遊戲是在一塊銅板裝置上,有三根杆(編號A、B、C),在A杆自下而上、由大到小按順序放置64個金盤(如下圖)。遊戲的目標:把A杆上的金盤全部移到C杆上,並仍保持原有順序疊好。操作規則:每次只能移動一個盤子,並且在移動過程中三根杆上都始終保持大盤在下,小盤在上,操作過程中盤子可以置於A、B、C任一杆上。
分析思路:設移動盤子數為n,為了將這n個盤子從A杆移動到C杆,可以做以下三步:
(1)以C盤為中介,從A杆將1至n-1號盤移至B杆;
(2)將A杆中剩下的第n號盤移至C杆;
(3)以A杆為中介;從B杆將1至n-1號盤移至C杆。
下面是漢諾塔實現的核心程式碼:
Java版:
public class HanoiTower { /** * 移動盤子 * topN:移動的盤子數 * from:起始塔座 * inter:中間塔座 * to:目標塔座 */ public static void doTower(int topN,char from,char inter,char to){ if(topN==1) { System.out.println("盤子1.從"+from+"塔座到"+to+"塔座"); }else { doTower(topN-1, from, to, inter); System.out.println("盤子"+topN+".從"+from+"塔座到"+to+"塔座"); doTower(topN-1, inter, from, to); } } }
C語言版:
#include<stdio.h> void move(int n,char a,char b,char c); int main() { int n; printf("請輸入要移動的塊數:"); scanf("%d",&n); move(n,'a','b','c'); } void move(int n,char a,char b,char c) { if(n==1) printf("\t%c->%c\n",a,c); //當n只有1個的時候直接從a移動到c else { move(n-1,a,c,b); //第n-1個要從a通過c移動到b printf("\t%c->%c\n",a,c); move(n-1,b,a,c); //n-1個移動過來之後b變開始盤,b通過a移動到c,這邊很難理解 } }
計算挪動步數的程式碼:
#include<stdio.h>
int main(void){
long long j=7; //最少為3個,最小步數為7
int i; /*i用來存放盤子的個數*/
printf("請輸入一個大於等於3,小於等於64的數:");
scanf("%d",&i);
if(i>64&&i<3)
{
printf("無法計算");
}
else{
for(int x=3;x<i;x++)
j=j*2+1;
} /*計算移動步數的公式*/
printf("%d個盤子要移動%ld步",i,j);
return 0;
}
如果你用第三個程式碼對挪動步數進行計算,會發現3個盤子需要7步,而6個盤子需要63步(呈指數增長),31個需要2147483647步。我們可想而知要是想挪64個盤子,數字是非常龐大的,那就是一個天文數字(程式計算溢位)。