汉诺塔问题(The Tower of Hanoi)的递归算法与非递归算法

非递归算法:

  根据圆盘的数量确定柱子的排放顺序:

    若n为偶数,按顺时针方向依次摆放 A B C;

    若n为奇数,按顺时针方向依次摆放 A C B。

  然后进行如下操作:

  (1)按顺时针方向把圆盘1从现在的柱子移动到下一根柱子,即当n为偶数时,若圆盘1在柱子A,则把它移动到B;若圆盘1在柱子B,则把它移动到C;若圆盘1在柱子C,则把它移动到A。

  (2)接着,把另外两根柱子上可以移动的圆盘移动到新的柱子上。即把非空柱子上的圆盘移动到空柱子上,当两根柱子都非空时,移动较小的圆盘。

  (3)反复进行(1)(2)操作,最后就能按规定完成汉诺塔的移动。

C++实现:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long LL;
struct Hanoi
{
    int n;
    struct Tower
    {
        char Name;
        stack<int> Disks;
    }Tow[3];
    void init(int num)
    {
        n=num;
        for(int i=0;i<3;i++)
        {
            Tow[i].Name='A'+i;
            while(!Tow[i].Disks.empty()) Tow[i].Disks.pop();
        }
        for(int i=n;i>=1;i--) Tow[0].Disks.push(i);
    }
    void solve()
    {
        LL cnt=0,cnt_max=(1<<n)-1;
        while(cnt<cnt_max)
        {
            cnt++;

            int flag1,flag2;
            if(cnt%2)//第奇数次的移动
            {
                for(int i=0;i<3;i++) if(!Tow[i].Disks.empty() && Tow[i].Disks.top()==1) flag1=i;
                if(n%2)//n为奇数
                    flag2=((flag1-1)+3)%3;
                else
                    flag2=(flag1+1)%3;
            }
            else//第偶数次的移动
            {
                flag1=flag2=-1;
                for(int i=0;i<3;i++)
                {
                    if(!Tow[i].Disks.empty() && Tow[i].Disks.top()==1) continue;

                    if(flag1==-1) flag1=i;
                    else if(flag2==-1) flag2=i;
                }

                if(!Tow[flag1].Disks.empty() && !Tow[flag2].Disks.empty())
                {
                    if(Tow[flag1].Disks.top()>Tow[flag2].Disks.top()) swap(flag1,flag2);
                }
                else
                {
                    if(Tow[flag1].Disks.empty()) swap(flag1,flag2);
                }
            }

            cout<<cnt<<": "<<"Move disk "<<Tow[flag1].Disks.top()<<" from "<<Tow[flag1].Name<<" to "<<Tow[flag2].Name<<endl;
            Tow[flag2].Disks.push(Tow[flag1].Disks.top());
            Tow[flag1].Disks.pop();
        }
    }
}hanoi;
int main()
{
    int n;
    cout<<"输入圆盘个数:"; cin>>n;
    hanoi.init(n);
    hanoi.solve();
}

 

 

递归算法:

设Hanoi(n,a,c,b)表示n个圆盘在a柱上,通过服从汉诺塔规则的若干步骤移动,在b柱的辅助下,全部按原顺序移动到了c柱上;

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long LL;
LL cnt;
void Hanoi(int n,char a,char c,char b)
{
    if(n==1)
    {
        cout<<++cnt<<": "<<"Move disk "<<n<<" from "<<a<<" to "<<c<<endl;
        return;
    }

    Hanoi(n-1,a,b,c);
    cout<<++cnt<<": "<<"Move disk "<<n<<" from "<<a<<" to "<<c<<endl;
    Hanoi(n-1,b,c,a);
    return;
}
int main()
{
    int n;
    cout<<"输入圆盘个数:";
    cin>>n;
    cnt=0;
    Hanoi(n,'A','C','B');
}

 

posted @ 2018-01-21 12:21  Dilthey  阅读(1360)  评论(0编辑  收藏  举报