careercup-栈与队列 3.4
3.4 在经典问题汉诺塔中,有3根柱子及N个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自底向上从大到小依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时有以下限制:
每次只能移动一个盘子;
盘子只能从柱子顶端滑出移到下一根柱子;
盘子只能叠在比它大的盘子上。
请运用栈,编写程序将所有盘子从第一根柱子移到最后一根柱子上。
使用递归的方法实现如下:
- #include<iostream>
- #include<stack>
- using namespace std;
- struct op
- {
- int begin;
- int end;
- char A;
- char B;
- char C;
- op(int start,int end,int A,int B,int C):begin(start),end(end),A(A),B(B),C(C) {}
- };
- void hanoi(int start,int end,char A,char B,char C)
- {
- stack<op> st;
- op tmp(start,end,A,B,C);
- st.push(tmp);
- while(!st.empty())
- {
- tmp=st.top();
- st.pop();
- if(tmp.begin!=tmp.end)
- {
- st.push(op(tmp.begin,tmp.end-,tmp.B,tmp.A,tmp.C));
- st.push(op(tmp.end,tmp.end,tmp.A,tmp.B,tmp.C));
- st.push(op(tmp.begin,tmp.end-,tmp.A,tmp.C,tmp.B));
- }
- else
- cout<<"move "<<tmp.begin<<" from "<<tmp.A<<" to "<<tmp.C<<endl;
- }
- }
- int main()
- {
- hanoi(,,'A','B','C');
- }
汉诺塔的递归解法讲完了,可是这并不是题目要求的。题目要求用栈来解决这个问题。 递归解法其实也是用到了栈的,在每次递归调用自己的时候, 将中间的状态参数压入栈中。不过这些操作都是系统隐式进行的, 所以你不用去关心它具体是怎么压栈出栈的。如果我们要用栈自己来实现这个过程, 就不得不考虑这其中的细节了。
接下来,我们就显式地用栈来实现递归过程中,这些状态参数的压栈出栈过程。首先, 我们需要定义一个数据结构来保存操作过程中的参数。
- struct op{
- int begin, end;
- char src, bri, dst;
- op(){
- }
- op(int pbegin, int pend, int psrc, int pbri, int pdst):begin(pbegin), end(pend), src(psrc), bri(pbri), dst(pdst){
- }
- };
其中的5个参数表示,在柱子src上有一叠圆盘,标号从begin到end, 要将它们从src移动到dst,中间可借助柱子bri。end其实相当于递归解法中的n, src,bri,dst与递归解法中的对应。那为什么还要定义begin这个变量呢? 为了判断柱子上是否只剩下一个盘子。如果begin等于end, 说明柱子上只剩下“最后”一个圆盘,可以进行移动。当然了, 用另外一个布尔变量来表示是否只剩下一个圆盘也是可以的,效果一样。 讲递归方法的时候,说到从初始状态到最终状态一共要经过以下几个状态:
- (~n, , ) (n, ~n-, ) (, ~n-, n) (, , ~n)
这些过程我们现在需要自己压栈出栈处理。压栈的时候不做处理,出栈时进行处理。因此, 压栈的时候需要与实际要操作的步骤相反。一开始,我们将最终想要完成的任务压栈。 听起来怪怪的,其实就是往栈中压入一组参数:
- stack<op> st; st.push(op(, n, src, bri, dst));
这组参数表示,柱子src上有1~n个圆盘,要把它移动到dst上,可以借助柱子bri。 当栈st不为空时,不断地出栈,当begin和end不相等时,进行三个push操作 (对应上面四个状态,相邻状态对应一个push操作,使状态变化), push与实际操作顺序相反(因为出栈时才进行处理,出栈时顺序就正确了), 如果,begin与end相等,则剩下当前问题规模下的“最后”一个圆盘,直接打印移动方案, hanoi代码如下:
C++实现代码:
- #include<iostream>
- #include<stack>
- using namespace std;
- struct op
- {
- int begin;
- int end;
- char A;
- char B;
- char C;
- op(int start,int end,int A,int B,int C):begin(start),end(end),A(A),B(B),C(C) {}
- };
- void hanoi(int start,int end,char A,char B,char C)
- {
- stack<op> st;
- op tmp(start,end,A,B,C);
- st.push(tmp);
- while(!st.empty())
- {
- tmp=st.top();
- st.pop();
- if(tmp.begin!=tmp.end)
- {
- st.push(op(tmp.begin,tmp.end-,tmp.B,tmp.A,tmp.C));
- st.push(op(tmp.end,tmp.end,tmp.A,tmp.B,tmp.C));
- st.push(op(tmp.begin,tmp.end-,tmp.A,tmp.C,tmp.B));
- }
- else
- cout<<"move "<<tmp.begin<<" from "<<tmp.A<<" to "<<tmp.C<<endl;
- }
- }
- int main()
- {
- hanoi(,5,'A','B','C');
- }
运行结果:
参考:http://www.cricode.com/304.html
careercup-栈与队列 3.4的更多相关文章
- 学习javascript数据结构(一)——栈和队列
前言 只要你不计较得失,人生还有什么不能想法子克服的. 原文地址:学习javascript数据结构(一)--栈和队列 博主博客地址:Damonare的个人博客 几乎所有的编程语言都原生支持数组类型,因 ...
- [ACM训练] 算法初级 之 数据结构 之 栈stack+队列queue (基础+进阶+POJ 1338+2442+1442)
再次面对像栈和队列这样的相当基础的数据结构的学习,应该从多个方面,多维度去学习. 首先,这两个数据结构都是比较常用的,在标准库中都有对应的结构能够直接使用,所以第一个阶段应该是先学习直接来使用,下一个 ...
- 剑指Offer面试题:6.用两个栈实现队列
一.题目:用两个栈实现队列 题目:用两个栈实现一个队列.队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能. 原文是使用 ...
- C实现栈和队列
这两天再学习了数据结构的栈和队列,思想很简单,可能是学习PHP那会没有直接使用栈和队列,写的太少,所以用具体代码实现的时候出现了各种错误,感觉还是C语言功底不行.栈和队列不论在面试中还是笔试中都很重要 ...
- JavaScript数组模拟栈和队列
*栈和队列:js中没有真正的栈和队列的类型 一切都是用数组对象模拟的 栈:只能从一端进出的数组,另一端封闭 FILO 何时使用:今后只要仅希望数组只能从一端进 ...
- 用JS描述的数据结构及算法表示——栈和队列(基础版)
前言:找了上课时数据结构的教程来看,但是用的语言是c++,所以具体实现在网上搜大神的博客来看,我看到的大神们的博客都写得特别好,不止讲了最基本的思想和算法实现,更多的是侧重于实例运用,一边看一边在心里 ...
- JavaScript中的算法之美——栈、队列、表
序 最近花了比较多的时间来学习前端的知识,在这个期间也看到了很多的优秀的文章,其中Aaron可能在这个算法方面算是我的启蒙,在此衷心感谢Aaron的付出和奉献,同时自己也会坚定的走前人这种无私奉献的分 ...
- Java数据结构和算法之栈与队列
二.栈与队列 1.栈的定义 栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表. (1)通常称插入.删除的这一端为栈顶(Top),另一端称为栈底(Bottom). (2)当表中没有元素时称为 ...
- python数据结构之栈、队列的实现
这个在官网中list支持,有实现. 补充一下栈,队列的特性: 1.栈(stacks)是一种只能通过访问其一端来实现数据存储与检索的线性数据结构,具有后进先出(last in first out,LIF ...
- 栈和队列的面试题Java实现【重要】
栈和队列: 面试的时候,栈和队列经常会成对出现来考察.本文包含栈和队列的如下考试内容: (1)栈的创建 (2)队列的创建 (3)两个栈实现一个队列 (4)两个队列实现一个栈 (5)设计含最小函数min ...
随机推荐
- Java多线程初学者指南(10):使用Synchronized关键字同步类方法
要想解决“脏数据”的问题,最简单的方法就是使用synchronized关键字来使run方法同步,代码如下: public synchronized void run() { ... } 从上面的代码可 ...
- [原博客] POJ 1740 A New Stone Game
题目链接题意:有n堆石子,两人轮流操作,每次每个人可以从一堆中拿走若干个扔掉(必须),并且可以从中拿走一些分到别的有石子的堆里(可选),当一个人不能拿时这个人输.给定状态,问是否先手必胜. 我们参考普 ...
- MySQL partition分区I
http://blog.csdn.net/binger819623/article/details/5280267 一. 分区的概念二. 为什么使用分区?(优点)三. ...
- Java使用JAX-WS来写webservice时 Unable to create JAXBContext
webservice,作为web开发人员来说必须掌握的一门技术,它的好处这里就不多说了,eclipse中自带了一种生成webservice的 方法,使用JAX-WS,如果我没有弄错的话,它需要java ...
- 《attodiskbenchmarks-v2.47》说明文件
对于用电脑方便且不喜欢在手机上乱装软件的我来说,很喜欢,特此整理,并在miui首发. 一.软件介绍 ATTO Disk Benchmark是一款电脑端使用的专业测速软件,该软件非常小巧,但却很专业,是 ...
- 好看的UI设计网站 www.ui.cn 和 插画网站 www.pixiv.net 千图网,界面很不错~
http://www.ui.cn/?t=share#project http://www.pixiv.net/ http://www.flaticon.com/ www.58pic.com 那张 给人 ...
- statspack系列7
原文:http://jonathanlewis.wordpress.com/2006/12/27/analysing-statspack-7/ 作者:Jonathan Lewis 这是一段Oracle ...
- bzoj3172
这里学习AC自动机其实对KMP和trie掌握好了之后很容易扩展成AC自动机的这里运用了一个性质由失配指针反向可以建成一棵fail树x串在y串中的出现的次数即为在fail树上以x结尾节点为根的子树中有多 ...
- 简单的单页c#生成静态页源码
protected void BtGroup_ServerClick(object sender, EventArgs e) { //产业群首页 ...
- BZOJ_1901_&_ZJU_2112_Dynamic_Rankings_(主席树+树状数组/线段树+(Treap/Splay))
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1901 给出一个长度为n的数列A,有m次询问,询问分两种:1.修改某一位置的值;2.求区间[l, ...