1. 程式人生 > >Mr.J--HanioTower(遞迴演算法)

Mr.J--HanioTower(遞迴演算法)

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個盤子,數字是非常龐大的,那就是一個天文數字(程式計算溢位)。