【说明】:
本文是左程云老师所著的《程序员面试代码指南》第一章中“用栈来实现汉诺塔问题”这一题目的C++栈方法的复现。
本文只包含问题描述、C++代码的实现以及简单的思路,不包含解析说明,具体的问题解析请参考原书。
感谢左程云老师的支持。
【题目】:
汉诺塔问题比较经典,这里修改一下游戏规则:现在限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧,而必须经过中间。求当有N层塔的时候,打印最优移动过程和最优移动总步数。
例如,当塔为两层时,最上层的塔记录为1,最下层的塔记录为2,则打印:
move 1 from left to mid
move 1 from mid to right
move 2 from left to mid
move 1 from right to mid
move 1 from mid to left
move 2 from mid to right
move 1 from left to mid
move 1 from mid to right
It will move 8 steps.
【思路】:
汉诺塔的第一个原则:不可以小压大;
汉诺塔的第二个原则:若求最优解,不可后退。
【编译环境】:
CentOS6.7(x86_64)
gcc 4.4.7
【实现】:
实现及测试代码:

/* *文件名:limitHanoi.cpp *作者: *问题描述:限制汉诺塔移动方法,只能由左到中,由中到左,由中到右,由右到中, * 不可直接由左到右,由右到左。 * 利用栈的结构求得最佳路径。 * 下面是C++/stack实现代码。 */ #include <iostream> #include <stack> #include <stdlib.h> using namespace std; enum Action { No = 0, LtoM = 1, MtoL = -1, RtoM = 2, MtoR = -2 }; /* *函数介绍:移动汉诺塔上的圆盘。 *输入参数:record为上一个移动的步骤;now为即将移动的步骤;src为源栈;dst为目的栈。 *输出参数:pre记录即将发生的移动步骤;src移动圆盘后的栈;dst移动圆盘后的栈。 *返回值:若圆盘移动成功,则返回移动歩数1;若失败,则返回移动歩数0。 */ int moveDisc(Action &record,Action now,stack<int> &src,stack<int> &dst) { if(!src.empty() && (abs(record) != abs(now)) && (dst.empty() || src.top() < dst.top()) ) { dst.push(src.top()); src.pop(); switch(now) { case 1: cout << "Move " << dst.top() << " from left to mid;" << endl; break; case -1: cout << "Move " << dst.top() << " from mid to left;" << endl; break; case 2: cout << "Move " << dst.top() << " from right to mid;" << endl; break; case -2: cout << "Move " << dst.top() << " from mid to right;" << endl; break; default: break; } record = now; return 1; } return 0; } /* *函数介绍:解决限制移动方式的汉诺塔问题的C++实现 *输入参数:layer为汉诺塔的层数 *输出参数:无 *返回值:为移动的歩数 */ int hanoiStack(int layer) { stack<int> lS,mS,rS; for(int i = layer; i > 0; i--) { lS.push(i); } Action record = No; int step = 0; while(rS.size() != layer) { step += moveDisc(record,LtoM,lS,mS); step += moveDisc(record,MtoL,mS,lS); step += moveDisc(record,RtoM,rS,mS); step += moveDisc(record,MtoR,mS,rS); } return step; } /* *函数介绍:测试代码 */ int main () { cout << "For 3 storey of Hanoi:" << endl; cout << "It will move " <<hanoiStack(3) <<" steps." << endl; return 0; }
【一点说明】:
这次题目的C++复现和左老师所写的略有差别,但是解题思路还是遵循这左老师所提出来的。
左程云老师还提出了使用递归方式的解法,有兴趣的同学可以去参考原书,下一篇我会将其使用C++的方式实现。
注:
转载请注明出处;
转载请注明源思路来自于左程云老师的《程序员代码面试指南》。