汉罗塔c++递归_栈与递归的区别

汉罗塔c++递归_栈与递归的区别汉罗塔问题是一个非常经典的算法,我们首先来研究一下修改的汉罗塔(简化步骤),在后面我们将来讲述经典的汉罗塔问题。题目:修改后的汉罗塔的规则:现在限制不能从最左侧的塔直接移动到最右侧,必需要经过中间;同时从最右侧移动到最左测试,同样必需经过中间;要求移动N层塔时,打印最优移动1、用递归函数实现(从最左移动到最右)分析:-当只有一层塔时,我们先需要将其从左移到中间,再从中间移动到右边,共分为

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

汉罗塔问题是一个非常经典的算法,我们首先来研究一下修改的汉罗塔(简化步骤),在后面我们将来讲述经典的汉罗塔问题。

题目:
修改后的汉罗塔的规则:现在限制不能从最左侧的塔直接移动到最右侧,必需要经过中间;同时从最右侧移动到最左测试,同样必需经过中间;要求移动N层塔时,打印最优移动

1、用递归函数实现(从最左移动到最右)

分析:
– 当只有一层塔时,我们先需要将其从左移到中间,再从中间移动到右边,共分为两步;如果它就在中间,那么我们只需要将它移动到左或则右,一步就行;
– 当我们有N 层塔时,我们需要先将1~N-1层塔移动到右边,然后移动第N层塔到中间,再将1~N-1层塔移动到最左边,将N层塔由中间移动右边;这样,第N层塔就移好了
– 接下来重复上述步骤,将1~N-2层塔移到最右边,将第N-1层塔移到最中间……(利用递归函数实现)

代码实现:

void  _HanoiProblem1(int num,string from,string to,int& count)//num代表塔的层数,from代表开始移动的位置(left,mid,right),to 代表要移动到的位置
{
    if(num == 1)//我们只有一层塔
    {
        if(from.compare("mid")==0 || to.compare("mid")==0)//此时只需直接移动
        {
            count++;
            cout<<"move "<<num<<" from "<<from.c_str()<<" to "<<to.c_str()<<endl;
        }
        else
        {
            cout<<"move "<<num<<" from "<<from.c_str()<<" to "<<"mid"<<endl;
            count++;
            cout<<"move "<<num<<" from "<<"mid"<<" to "<<to.c_str()<<endl;
            count++;
        }
    }
    else//我们有多层塔
    {
        if(from.compare("mid")==0 || to.compare("mid")==0)
        {
            string another;
            if(from.compare("left")==0)
                another = "right";
            else
                another = "left";

            _HanoiProblem1(num-1,from,another,count);//例如从左移到中间,先将1~N-1层塔移动到右边,
            cout<<"move "<<num<<" from "<<from.c_str()<<" to "<<to.c_str()<<endl;//再将第N层塔移到中间
            count++;
            _HanoiProblem1(num-1,another,to,count);//再将1~N-1层塔移到中间

        }
        else//从左移到右或从右移到左
        {
            _HanoiProblem1(num-1,from,to,count);//例如从左移到右,先将1~N-1层塔从左移动到右边,
            cout<<"move "<<num<<" from "<<from.c_str()<<" to "<<"mid"<<endl;//再将第N层塔移到中间
            count++;
            _HanoiProblem1(num-1,to,from,count);//再将1~N-1层塔从右移动到左边
            cout<<"move "<<num<<" from "<<"mid"<<" to "<<to.c_str()<<endl;//再将第N层塔从中间移到右边
            count++;
            _HanoiProblem1(num-1,from,to,count);//再将1~N-1层塔从左移动到右边
        }
    }
}
void HanoiProblem1(int num,string from,string to)
{
    int count = 0;
    _HanoiProblem1(num,from,to,count);
    cout<<"count is: "<<count<<endl;
}

测试代码:

void funtest()
{
    HanoiProblem1(2,"left","right");
}

int main()
{
    funtest();
    getchar();
    return 0;
}

结果图
这里写图片描述

2.用栈模拟实现

分析:
我们上面用递归实现,我们已经知道了基本的走法,接下来我们用栈来模拟汉罗塔问题,将塔的移动转换为入栈和出栈的操作,但是,由题我们知道了参数入栈和出栈的两个基本规则

  • 小压大问题,即只有当要入栈的参数小于栈顶元素,这时我们才能入栈
  • 动作不想临,题目要求我们实现最优移动,所以我们从左移动到中间,下一步将它从中间右移动到左边,是没有意义的

满足了以上两条规则,我们现在看移动的过程,一个塔a,只有四中可能的动作,从左到中,从中到右,从右到中,从中到左,但是要满足以上两种规则我们发现它只有一种动作可以走;例如:a在最左边,第一次,它只能从左到中间,第二次,由规则知,从左到中间不行,从中间到左没有意义,那么只剩下从中间到右和从右到中间,我们只需判断就能得到结果。

代码实现:

enum action
{
    No,
    LToM,
    MToL,
    RToM,
    MToR,
};

int fStackToStack(action& record,action preAction,action nowAction,stack<int>& fstack,stack<int>& tstack,string from,string to)
{
    if(record != preAction && fstack.top() < tstack.top())//满足两条准则,动作不可逆和小压大原则
    {
        int data = fstack.top();
        fstack.pop();
        tstack.push(data);
        cout<<"move "<<data<<" from "<<from.c_str()<<" to "<<to.c_str()<<endl;
        record = nowAction;
        return 1;
    }
    return 0;
}

int HanoiProblem2(int num,string left,string mid,string right)
{
    stack<int> ls;
    stack<int> ms;
    stack<int> rs;

    ls.push(INT_MAX);
    ms.push(INT_MAX);
    rs.push(INT_MAX);

    for(int idx=num; idx>0; --idx)
        ls.push(idx);

    action record = No;//记录上一步的动作
    int count = 0;

    while(rs.size() != num+1)
    {
        count += fStackToStack(record,MToL,LToM,ls,ms,left,mid);
        count += fStackToStack(record,LToM,MToL,ms,ls,mid,left);
        count += fStackToStack(record,MToR,RToM,rs,ms,right,mid);
        count += fStackToStack(record,RToM,MToR,ms,rs,mid,right);
    }
    return count;
}

测试代码:

void funtest()
{
    int ret = HanoiProblem2(2,"left","mid","right");
    cout<<ret<<endl;
}

int main()
{
    funtest();
    getchar();
    return 0;
}

结果图:
这里写图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/183281.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • docker 卸载出错

    docker 卸载出错场景:win10,一时脑抽,在安装了docker之后没有用正常的方式卸载(比如win10卸载,软件管家等)。直接把docker在c盘下的文件夹给删了,结果这一删,再也安不上了。现象:安装docker显示已经是最新版本(Existinginstallationisuptodate),如下图解决方法:…

    2022年9月8日
    2
  • SQLSERVER存储过程语法的具体解释

    SQLSERVER存储过程语法的具体解释

    2022年1月11日
    26
  • 再生龙硬盘对拷使用教程_linux系统怎样备份

    再生龙硬盘对拷使用教程_linux系统怎样备份教程1再生龙备份恢复说明:准备两个u盘,一个做再生龙的启动盘,一个做存储镜像文件的盘1.下载再生龙2.下载工具tuxboot制作u启(1)https://sourceforge.net/projects/tuxboot/files/0.8/Windows/3.制作u盘启动盘(1)Clonezilla镜像:clonezilla-live-2.6.1-25-amd64.zip(2)Clon…

    2025年7月3日
    2
  • BloomFilter怎么用?使用布隆过滤器来判断key是否存在?「建议收藏」

    BloomFilter怎么用?使用布隆过滤器来判断key是否存在?「建议收藏」今天跟一个同事聊了一个问题,说最近在做推荐,如何判断用户是否看过这个片段呢?想了一下,正好可以使用布隆过滤器来完成这个需求。布隆,可不是LOL的布隆。我们的这个布隆是一个叫布隆的外国人,在1970年提出的一种方案:如果判断这个key不存在,那么就一定不存在,如果key存在,那么有可能不存在。所以不存在的时候,你永远可以详细布隆。布隆过滤器是一个高空间利用率的概率性数据结构,由BurtonBloom于1970年提出,用于测试一个元素是否在集合中。新创建的布隆过滤器是一串被置为0的Bit数组(假设有m位),

    2025年6月1日
    2
  • 河南六大学生程序设计竞赛–外国人饲喂站[通俗易懂]

    河南六大学生程序设计竞赛–外国人饲喂站

    2022年1月16日
    55
  • python modis数据拼接_python读取modis数据

    python modis数据拼接_python读取modis数据本期记录只上干活,废话不多说,主要是后面与HEG配合使用,实现一系列研究与反演操作。python环境:Python3.5.2+Pycharm模块包:pyhdf安装方法(命令行输入):pipinstallpyhdf一、获取hdf数据集:frompyhdf.SDimportSDHDF_FILR_URL=”E:\Persona_project\Py-Program\RS\modis\M…

    2025年6月24日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号