zoukankan      html  css  js  c++  java
  • 非递归汉斯塔

    最近在看了大学算法的教程后,深深地理解到了递归算法在某些情况下的局限性,于是就想到了两年前自己做的汉斯塔的项目中的递归算法。能否将其变成循环算法呢?

    为了简化,我是在VC++的控制台下来完成这个算法。

    为了让程序更加清晰,定义了两个类Peg(柱子类),Disk(盘子类),当然内容就简化多了。类图如下:

      

    Peg表示柱子类

    Disks:vector<int>表示这个柱子上的所有盘子

    Name:int表示柱子的名称。我将柱子将0,1,2进行了编号。以便接下来的运算

    Disk表示盘子类

           Now:int   表示这个盘子现在所在的柱子

           WantTo:int      表示这个盘子将要移到哪个柱子上去

    CLoopMove里就是有关用循环移盘子的算法

           对外的唯一接口就是LoopMove(int n):void ,参数n表示有几个盘子。

          

    下面详细说明这个函数的实现过程:

    1.先申明三个柱子对象

           Peg p0(0);      //起始柱

           Peg p1(1);      //目标柱

           Peg p2(2);      //辅助柱

    然后将所以的盘子放在p1上

           为了操作方便,将这个三个变量放在数组中

    Peg pegs[3]={p0,p1,p2};

    2.接下来定义所有的盘子,并且现在盘子都在柱子0上。

           vector<Disk> disks;

           for (int i=0; i<n; ++i)

           {

                  disks.push_back(Disk(0));

           }

    3.由于用数学归纳法,很容易得出移动n个盘子的步数是2n-1,所以只需要循环这么多次就完成任务(如果不计算次数,也可以用死循环,并且在循环内判断游戏是否结束)。在每次循环中,       都调用FindMove()方法,来更新每个盘子的WantTo属性。具体的做法是:

           1.最大的盘子,也就是第n-1个盘子的目标肯定是p1

           2.循环从n-2个盘子到第0个盘子

                  在循环中判断,比每个盘子大一的盘子是否已移到位。

                  如果没有到位,则它应该移到“第三者”上去

                         disks[i].WantTo = 3 - disks[i+1].Now - disks[i+1].WantTo;  //这句代码最经典

                         比如,n-1号盘现在在0号柱上,要移到1号柱子上,那么n-2号柱子则应在2号柱上

                  如果已到位,则这个盘子也应在这个柱子上

                         disks[i].WantTo = disks[i+1].WantTo;

    4.将FindMove调用完后,就只需要从最小的盘子开始访问,看哪个需要移动,就移动之。

    上面就是所有的程序结构,可以看出还有很大的优化空间,不用每次都去调用FindMove判断。

    并且我现在的这个FindMove算法可以支持半自动。也就是不一定非要从所有的盘在p0上这个状态开始,可以从任何状态开始(当然小盘必须在大盘上面)。

    在项目中,用递归的汉斯塔来进行比较,发现这个循环版本没有错误。代码下载:《非递归汉斯塔

  • 相关阅读:
    软件架构设计模式简述
    [翻译]docker生态圈Mindmap
    完美解决Invalid layout of java.lang.String at value问题的方法
    用开源项目JazzyViewPager实现ViewPager切换动画
    用开源项目RangBar来实现有范围的SeekBar
    开源项目MultiChoiceAdapter详解(六)——GridView和MultiChoiceBaseAdapter配合使用
    开源项目MultiChoiceAdapter详解(五)——可扩展的MultiChoiceBaseAdapter
    开源项目MultiChoiceAdapter详解(四)——MultiChoiceBaseAdapter的使用
    开源项目MultiChoiceAdapter详解(三)——MulitChoiceNormalArrayAdapter的使用
    开源项目MultiChoiceAdapter详解(二)——MultiChoiceArrayAdapter的使用
  • 原文地址:https://www.cnblogs.com/xiangism/p/1726039.html
Copyright © 2011-2022 走看看