1. 程式人生 > >漢諾塔非遞迴演算法分析與實現

漢諾塔非遞迴演算法分析與實現

漢諾塔的遞迴演算法很容易理解,也非常容易實現。下面,本文討論了漢諾塔問題的非遞迴演算法,核心內容就是棧的使用技巧。
首先,對於每個柱子來說,就是一個棧,這個棧有個特點就是,大數放在下面,小數放在上面。在首次建立棧時,我們可以先儲存好這些資料,假設最小的盤子序號為1,後面的由此類推。在建立棧時,根據當前盤子總數是否為偶數,需要調整B、C兩個柱子的位置。當n為偶數時,按照A、B、C的順序排放三個柱子,當n為奇數時,按照A、C、B的順序排列這些柱子。這兩個順序就是漢諾塔中最小的那個盤子的挪動順序。
其次,建立好棧後,接下來就是演算法的核心部分了。初始情況下,需要首先挪動最小的那個盤子,把編號為1的那個盤子挪動到它的下一個位置上(有可能是B,也有可能是C),這時需要判斷一下,程式是否已經完成了,若還沒有完成,則繼續下面的步驟。下一步,判斷當前剩下的兩個柱子的棧頂元素,如果有個棧頂元素為0,說明該柱子上沒有盤子,把非零的棧頂元素放入空棧中;如果兩個棧頂元素都是非零的,則將較小的元素移動到較大的元素上面。
再次,此時一輪迴圈已經結束,再次移動編號為1的盤子,將它移動到它的下一個位置上面。
最後,重複上面的步驟,當迴圈結束時,我們的演算法就執行完了。

// NonRecursionHanoi.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<iostream>

using namespace std;

const int MAX = 64;

struct st
{
    char name;
    int array[MAX];
    int topIndex;

    int TopData( void )
    {
        if( topIndex == 0 )
        {
            return
0; } else { return array[topIndex-1]; } } int Pop( void ) { int retVal = array[topIndex-1]; --topIndex; array[topIndex] = 0; return retVal; } void Push( int data ) { array[topIndex] = data; ++topIndex; } }; long
int expo( int x, int y ) { long retVal = 1; for( int i = 0; i < y; i++ ) { retVal = retVal * x; } return retVal; } void CreateHanoi( st pillar[], int n ) { pillar[0].name = 'A'; for(int i = 0; i < n; i++ ) { pillar[0].array[i] = n - i; } pillar[0].topIndex = n; for( int i = 0; i < n; i++ ) { pillar[2].array[i] = pillar[1].array[i] = 0; } pillar[2].topIndex = pillar[1].topIndex = 0; if( n%2 == 0 ) { pillar[1].name = 'B'; pillar[2].name = 'C'; } else { pillar[1].name = 'C'; pillar[2].name = 'B'; } } int _tmain(int argc, _TCHAR* argv[]) { int n; cout<<"Please input the disk number:"; cin>>n; while ( ( n > 64 ) || ( n < 1 ) ) { cout<<"\r\nInput a New number, must between 1 and 64"<<endl; cin>>n; } st pillar[3]; CreateHanoi( pillar, n ); int max = expo( 2, n ) - 1; // Move n Disks need max steps. int k = 0; // Record the Current move steps. int j = 0; // Record 1st disk's position. while( k < max ) { int temp = pillar[j%3].Pop(); pillar[(j+1)%3].Push(temp); cout<<++k<<" "<<pillar[j%3].name<<"->"<<pillar[(j+1)%3].name<<endl; ++j; int temp1 = pillar[(j-1)%3].TopData(); int temp2 = pillar[(j+1)%3].TopData(); if( k < max ) { if( ( temp2 == 0 ) || ( ( temp1 > 0 ) && ( temp2 > temp1 ) ) ) { temp = pillar[(j-1)%3].Pop(); pillar[(j+1)%3].Push(temp); cout<<++k<<" "<<pillar[(j-1)%3].name<<"->"<<pillar[(j+1)%3].name<<endl; } else { temp = pillar[(j+1)%3].Pop(); pillar[(j-1)%3].Push(temp); cout<<++k<<" "<<pillar[(j+1)%3].name<<"->"<<pillar[(j-1)%3].name<<endl; } } } getchar(); getchar(); return 0; }