汉诺塔非递归算法分析与实现

汉诺塔的递归算法很容易理解,也非常容易实现。下面,本文讨论了汉诺塔问题的非递归算法,核心内容就是栈的使用技巧。
首先,对于每个柱子来说,就是一个栈,这个栈有个特点就是,大数放在下面,小数放在上面。在首次建立栈时,我们可以先存储好这些数据,假设最小的盘子序号为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;
}

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
汉诺塔是一个经典的递归问题,但也可以使用非递归算法来解决。下面是一个使用C语言实现非递归算法: ```c #include <stdio.h> #include <stdlib.h> typedef struct { int n; char source, temp, dest; } State; typedef struct { State *array; int size; int top; } Stack; Stack *createStack(int size) { Stack *stack = (Stack *) malloc(sizeof(Stack)); stack->array = (State *) malloc(sizeof(State) * size); stack->size = size; stack->top = -1; return stack; } void push(Stack *stack, State state) { stack->array[++stack->top] = state; } State pop(Stack *stack) { return stack->array[stack->top--]; } void hanoi(int n, char source, char temp, char dest) { Stack *stack = createStack(n); push(stack, (State) {n, source, temp, dest}); while (stack->top >= 0) { State currentState = pop(stack); if (currentState.n == 1) { printf("Move disk from %c to %c\n", currentState.source, currentState.dest); } else { push(stack, (State) {currentState.n - 1, currentState.temp, currentState.source, currentState.dest}); push(stack, (State) {1, currentState.source, currentState.temp, currentState.dest}); push(stack, (State) {currentState.n - 1, currentState.source, currentState.dest, currentState.temp}); } } free(stack->array); free(stack); } int main() { int n; printf("Enter the number of disks: "); scanf("%d", &n); hanoi(n, 'A', 'B', 'C'); return 0; } ``` 这个算法使用了一个栈来模拟递归的过程。首先将初始状态压入栈中,然后在每一次循环中取出栈顶状态进行处理。当只有一个盘子时,直接移动即可,否则将分解成三个子问题,分别将n-1个盘子从源柱移动到辅助柱,将最后一个盘子从源柱移动到目标柱,最后将n-1个盘子从辅助柱移动到目标柱。循环直到栈为空,即所有盘子都移动到了目标柱。 示例代码中的hanoi函数接受三个参数:n表示盘子的个数,source表示源柱,temp表示辅助柱,dest表示目标柱。在每一次移动盘子时,会打印出移动的步骤。 你可以在程序中输入想要的盘子数量,然后运行该程序来查看非递归算法的结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值