队列实现栈 | 栈实现队列

⼀、 ⽤栈实现队列

首先,队列的 API 如下:

class MyQueue {/** 添加元素到队尾 */public void push(int x);/** 删除队头的元素并返回 */public int pop();/** 返回队头元素 */public int peek();/** 判断队列是否为空 */public boolean empty();
}

我们使⽤两个栈 s1, s2 就能实现⼀个队列的功能(这样放置栈可能更容易理解) :

class MyQueue {private Stack<Integer> s1, s2;public MyQueue() {s1 = new Stack<>();s2 = new Stack<>();}// ...
}

当调用 push 让元素入队时,只要把元素压入 s1 即可,比如说 push 进 3 个元素分别是 1,2,3,那么底层结构就是这样:

/** 添加元素到队尾 */
public void push(int x) {s1.push(x);
}

那么如果这时候使用 peek 查看队头的元素怎么办呢?按道理队头元素应该是 1,但是在 s1 中 1 被压在栈底,现在就要轮到 s2 起到一个中转的作用了:s2 为空时,可以把 s1 的所有元素取出再添加进 s2,这时候 s2 中元素就是先进先出顺序了。

/** 返回队头元素 */
public int peek() {if (s2.isEmpty())// 把 s1 元素压入 s2while (!s1.isEmpty())s2.push(s1.pop());return s2.peek();
}

同理,对于 pop 操作,只要操作 s2 就可以了

/** 删除队头的元素并返回 */
public int pop() {// 先调用 peek 保证 s2 非空peek();return s2.pop();
}

最后,如何判断队列是否为空呢?如果两个栈都为空的话,就说明队列为空:

/** 判断队列是否为空 */
public boolean empty() {return s1.isEmpty() && s2.isEmpty();
}

C++代码:

class MyQueue {public:
//主要思想是定义两个栈,一个用来存放入队元素的栈s1,另一个栈
//用来进行出队操作的s2,往队列中插元速时,直接往s1中插入,出队时,
//如果s2不为空,直接在s2中进行出栈操作,如果s2为空,就把s1中元素全部放到s2中/** Initialize your data structure here. */MyQueue() {}/** Push element x to the back of queue. */void push(int x) {//直接往s1中插入s1.push(x);}/** Removes the element from in front of queue and returns that element. */int pop() {//进行出队操作时,如果s2为空,就直接把s1中元素先移动到s2中,//在进行出队操作,如果s2不为空,直接在s2中直接出队,注意不能在s2有//元素时把s1中的元素移动到s2中,这样顺序回乱int data;if(s2.empty()){while(s1.size()){s2.push(s1.top());s1.pop();}data = s2.top();s2.pop();}else{data = s2.top();s2.pop();}return data;}/** Get the front element. */int peek() {int data;if(s2.empty()){while(s1.size()){s2.push(s1.top());s1.pop();}data = s2.top();//s2.pop();}else{data = s2.top();//s2.pop();}return data;}/** Returns whether the queue is empty. */bool empty() {return s1.empty() && s2.empty();}private:stack<int> s1;stack<int> s2;
};

二、用队列实现栈

首先看下栈的 API:

class MyStack {/** 添加元素到栈顶 */public void push(int x);/** 删除栈顶的元素并返回 */public int pop();/** 返回栈顶元素 */public int top();/** 判断栈是否为空 */public boolean empty();
}

先说 push API,直接将元素加入队列,同时记录队尾元素,因为队尾元素相当于栈顶元素,如果要 top 查看栈顶元素的话可以直接返回:

class MyStack {Queue<Integer> q = new LinkedList<>();int top_elem = 0;/** 添加元素到栈顶 */public void push(int x) {// x 是队列的队尾,是栈的栈顶q.offer(x);top_elem = x;}/** 返回栈顶元素 */public int top() {return top_elem;}
}

我们的底层数据结构是先进先出的队列,每次 pop 只能从队头取元素;但是栈是后进先出,也就是说 pop API 要从队尾取元素

解决方法简单粗暴,把队列前面的都取出来再加入队尾,让之前的队尾元素排到队头,这样就可以取出了:

/** 删除栈顶的元素并返回 */
public int pop() {int size = q.size();while (size > 1) {q.offer(q.poll());size--;}// 之前的队尾元素已经到了队头return q.poll();
}

这样实现还有一点小问题就是,原来的队尾元素被提到队头并删除了,但是 top_elem 变量没有更新,我们还需要一点小修改:

/** 删除栈顶的元素并返回 */
public int pop() {int size = q.size();// 留下队尾 2 个元素while (size > 2) {q.offer(q.poll());size--;}// 记录新的队尾元素top_elem = q.peek();q.offer(q.poll());// 删除之前的队尾元素return q.poll();
}

最后,API empty 就很容易实现了,只要看底层的队列是否为空即可:

/** 判断栈是否为空 */
public boolean empty() {return q.isEmpty();
}

当然可以用两个队列来实现一个栈:

C++代码:

class MyStack {public:
//主要思想是定义两个队列,入栈时,如果两个队列同时为空,就随便往一个队列中插入
//如果其中有一个队列不为空,每次插就往非空的队列中插入。出栈时,每次把非空队列的
//前size-1个元素移动到空队列中,原非空队列就只剩下最后一个元素,这个元素满
//足栈的要求,直接出队。总之,主要思想是把两个队列中的元素来回移动,每次剩下最后
//一个元素直接出队,就相当于是栈顶元素/** Initialize your data structure here. */MyStack() {queue<int> q1;queue<int> q2;}/** Push element x onto stack. */void push(int x) {//如果两个队列都为空,随便插入到一个队列中,反之插入到非空队列中if(!q1.empty()){q1.push(x);}else{q2.push(x);}}/** Removes the element on top of the stack and returns that element. */int pop() {//每次把非空队列中的前size-1个元素移动到空队列中去,原非空队列//剩下最后一个元素就相当于栈顶元素,出栈时,就直接出队int data; if(q1.empty()){while(q2.size() > 1){q1.push(q2.front());q2.pop();}data = q2.front();q2.pop();}else{while(q1.size() > 1){q2.push(q1.front());q1.pop();}data = q1.front();q1.pop();}return data;}/** Get the top element. */int top() {//返回非空队列的队尾元素,就相当于栈顶元素,if(!q1.empty()){return q1.back();}else{return q2.back();}}/** Returns whether the stack is empty. */bool empty() {//两个队列同时为空是,此时才表明栈中没有任何元素return q1.empty() && q2.empty();}private:queue<int> q1;queue<int> q2;
};

队列实现栈 | 栈实现队列相关推荐

  1. 【数据结构】单调栈和单调队列 详解+例题剖析

    算法:单调栈和单调队列 一.单调栈和单调队列 二.单调栈例题 1.模板题入门 2.不懂不要急,看这道题 三.单调队列例题 1.入门 2.进阶 一.单调栈和单调队列 单调栈和单调队列与普通的栈,队列不同 ...

  2. python中的队列和栈_python的队列和栈

    (一)队列和栈的区别 1.队列: 队列是一种特殊的线性表.其两头都有限制,插入只能在表的一端进行(只进不出),而删除只能在表的另一端进行(只出不进),允许删除的一端称为队尾(rear),允许插入的一端 ...

  3. 多态指针访问虚函数不能被继承的类快速排序N皇后问题插入排序堆排序merge归并排序栈上生成对象两个栈实现一个队列...

    多态 /*1. 要想实现覆盖(重写)父类必须声明为virtual,子类可以不声明为virtual.-->FunB()2. 派生类重写基类的虚函数实现多态,要求函数名.参数列表.返回值完全相同.( ...

  4. 用栈来表示队列,用队列来表示栈

    这个问题总的栈和队列,没有自己手写,自己手写太浪费了,于是就用的java中的集合框架list下面的LinkedList 其实LinkedList既可以当做栈用,也可以当做队列来使用. 作为栈的时候,L ...

  5. 【剑指offer】用两个栈实现一个队列

    题目:两个栈实现一个队列. 栈的特点:先进后出,队列的特点是先进先出 思路:stack1放入数据:pop时,先判断stack2是否为空,如果不为空,直接pop,如果空,则push(stack1.pop ...

  6. 【C++ 语言】容器 ( queue 队列 | stack 栈 | priority_queue 优先级队列 | set 集合 | 容器遍历 | map )

    文章目录 queue 队列 stack 栈 priority_queue 优先级队列 priority_queue 优先级队列指定排序方法 priority_queue 优先级队列排序行为 prior ...

  7. 剑指offer五:两个栈实现一个队列

    题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. package com.jianzhioffer;import java.util.Stack;publ ...

  8. sdut 3335 数据结构实验之栈与队列八:栈的基本操作

    数据结构实验之栈与队列八:栈的基本操作 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem Descri ...

  9. 两个栈实现一个队列,两个队列实现一个栈

    题目:用两个栈实现一个队列,用两个队列实现一个栈. 首先要了解栈和队列这两种数据结构各自的特点,栈是一种后入先出(Last In First Out,LIFO)的数据结构,队列是一种先进先出(Firs ...

  10. python 用两个栈实现一个队列

    | 两个栈实现队列 用两个栈实现一个队列.队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能.(若队列中没有元素 ...

最新文章

  1. 用Leangoo项目管理工具怎么做多团队大规模Scrum敏捷开发?
  2. 【Spring】DispatcherServlet的启动和初始化
  3. 求最值(最大值和最小值)
  4. 物理化学 焓变的计算,学会状态的转变
  5. VTK:PolyData之DijkstraGraphGeodesicPath
  6. OpenLayers3基础教程——OL3之Popup
  7. App设计灵感之十二组精美的智能家居操作App设计案例
  8. NJUST4316(立体几何投影的面积交)
  9. io 错误: socket closed_Tomcat NIO(9)IO线程Overall流程和关键类
  10. 自己攒的正则表达式---判断汉字、字符但不要数字
  11. 16进制与字符串相互转换(C语言)
  12. 109 个实用 shell 脚本
  13. 计算机实验报告双绞线制作,双绞线的制作实验报告.docx
  14. Matlab中常用的清除命令clc,clear,clf等
  15. 轻松解决mscorsvw.exe进程CPU占用高的问题
  16. wps如何自己制作流程图_wps流程图怎么制作(wps快速生成流程图)
  17. mysql 计算自然周
  18. python学习之人民币兑美元之间的转换
  19. 用python3根据配置自动生成自定义图片logo(一键解决图片侵权困扰)
  20. 基于zynq的SGMII调试

热门文章

  1. win10使用自带虚拟机没有Hyper-V场景
  2. Centos7KVM的安装与配置及创建虚拟机
  3. SQL2005 express升级到2008企业版解决4096限制问题
  4. 网狐框架分析八--web登录游戏大厅流程
  5. 【SpringMVC】SpringMVC基础-SpringMVC项目快速搭建、日志框架为logback
  6. 【算法】K-Means聚类算法(k-平均或k-均值)
  7. Greenplum 表空间和filespace的用法
  8. Notepad++去除代码行号的几种方法
  9. TI Davinci DM6446开发攻略——开发环境搭建
  10. 方便的画拓扑图的软件,大家一起分享