用栈实现队列

力扣题目链接(opens new window)

使用栈实现队列的下列操作:

push(x) -- 将一个元素放入队列的尾部。

pop() -- 从队列首部移除元素。

peek() -- 返回队列首部的元素。

empty() -- 返回队列是否为空。

示例:

MyQueue queue = new MyQueue();
queue.push(1);
queue.push(2);
queue.peek(); // 返回 1
queue.pop(); // 返回 1
queue.empty(); // 返回 false

说明:

  • 你只能使用标准的栈操作 -- 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
  • 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)

栈的基本操作

示例:

#include <stack>

//栈容器常用接口
void test01()
{
//创建栈容器 栈容器必须符合先进后出
stack<int> s; //向栈中添加元素,叫做 压栈 入栈
s.push(10);
s.push(20);
s.push(30); while (!s.empty()) {
//输出栈顶元素
cout << "栈顶元素为: " << s.top() << endl;
//弹出栈顶元素
s.pop();
}
cout << "栈的大小为:" << s.size() << endl; } int main() { test01(); system("pause"); return 0;
}

总结:

  • 入栈 --- push
  • 出栈 --- pop
  • 返回栈顶 --- top
  • 判断栈是否为空 --- empty
  • 返回栈大小 --- size

思路

题意是要模拟一个队列的行为,用栈

队列是什么?前后都打开的一种结构,也就是说可以实现先进先出

这点用一个栈不太好还原,所以要模拟先进先出至少得使用两个 stack ,

分别为进栈(stack_in)和出栈(stack_out)

当模拟队列 push 时,我们同样只需要将数据 push 进 stack_in 即可,该动作可以直接调用官方为stack提供的 push 函数

当模拟队列 pop 时,我们要先将 stack_in 的所有数据 pop 出来再 push 进 stack_out 。

此时,之前先进入 stack_in 的数据就在 stack_out 的 top 位置了,剩下的我们只需要对 stack_out 进行 pop 操作即可模拟队列的pop。

对应的模拟动画如下:

注意:在将 stack_in 的数据放入 stack_out 之前,必须先检查 stack_out 是否为空,不为空就直接从stack_out 往外弹数据。且往放 stack_out 数据时必须一次性全部放完,不然上述两种情况都会导致数据的顺序出错。

代码

步骤:(实现pop)

1、判断出栈是否为空

2、循环将入栈数据压入出栈

3、然后从stack_out的栈顶获取数据

class MyQueue {
public:
//定义两个栈
stack<int>stack_in;
stack<int>stack_out; MyQueue() { } void push(int x) {
stack_in.push(x);
} int pop() {
int tmp;
//判断stack_out是否为空,不为空就往里面不断push数据
if(stack_out.empty()){
//将stack_in的全部数据push入
while(!stack_in.empty()){
// stack_out.push(stack_in.pop()) //错误,应该让stack_out先获取stack_in的栈顶数据,然后再pop走
// stack_out.push(stack_in.top());//虽然在本题不会报错,但
// stack_in.pop();//这种写法会在别的同类型的题中出错,所以统一使用下面的写法
tmp = stack_in.top();
stack_in.pop();
stack_out.push(tmp);
}
}
//然后从stack_out获取数据
int res = stack_out.top();
stack_out.pop();
return res; } int peek() {//即查看栈顶数据
int res = this->pop();//直接复用类内的pop
//然后记得再把数据push回来
stack_out.push(res);
return res; } bool empty() {
return stack_in.empty() && stack_out.empty();
}
};
注意点

1、对栈进行pop操作是没有返回值的,也就是说pop之后,栈顶的数据就没了,要读数据用top读

2、能复用就复用,优雅且专业

用队列实现栈

力扣题目链接(opens new window)

使用队列实现栈的下列操作:

  • push(x) -- 元素 x 入栈
  • pop() -- 移除栈顶元素
  • top() -- 获取栈顶元素
  • empty() -- 返回栈是否为空

注意:

  • 你只能使用队列的基本操作-- 也就是 push to back, peek/pop from front, size, 和 is empty 这些操作是合法的。
  • 你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
  • 你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)

queue基本操作

示例:

#include <queue>
#include <string>
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
} string m_Name;
int m_Age;
}; void test01() { //创建队列
queue<Person> q; //准备数据
Person p1("唐僧", 30);
Person p2("孙悟空", 1000);
Person p3("猪八戒", 900);
Person p4("沙僧", 800); //向队列中添加元素 入队操作
q.push(p1);
q.push(p2);
q.push(p3);
q.push(p4); //队列不提供迭代器,更不支持随机访问
while (!q.empty()) {
//输出队头元素
cout << "队头元素-- 姓名: " << q.front().m_Name
<< " 年龄: "<< q.front().m_Age << endl; cout << "队尾元素-- 姓名: " << q.back().m_Name
<< " 年龄: " << q.back().m_Age << endl; cout << endl;
//弹出队头元素
q.pop();
} cout << "队列大小为:" << q.size() << endl;
} int main() { test01(); system("pause"); return 0;
}

总结:

  • 入队 --- push
  • 出队 --- pop
  • 返回队头元素 --- front
  • 返回队尾元素 --- back
  • 判断队是否为空 --- empty
  • 返回队列大小 --- size

思路

用一个队列就可以模拟栈的行为

一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时再去弹出元素就是栈的顺序了。

代码

步骤:(实现pop)

1、获取队列长度qLen

2、循环,只需循环qLen-1的部分,最后一个元素不用动。不断获取队头数据再加入队尾,然后pop调当前数据

3、循环结束后,现在队中元素的顺序就颠倒了(与栈顺序一致),接下来就从队头拿数据就行,

class MyStack {
public:
//创建队列
queue<int> q; MyStack() { } void push(int x) {
q.push(x);
} int pop() {
//获取队列长度
int qLen = q.size();
//需要循环的部分不包含最后一个数
qLen--;
while(qLen--){
//将队头的数据push到队尾
q.push(q.front());
//弹出当前队头数据
q.pop();
}
//已获得需要的数据顺序
//一个一个获取即可
int res = q.front();
q.pop();
return res;
} int top() {
//在栈里面的第一个元素,其实就是队列的最后一个元素,用back方法可以获取到
return q.back();
} bool empty() {
return q.empty();
}
};

TBD

【LeetCode栈与队列#01】队列的基本操作:用栈模拟队列和用队列模拟栈的更多相关文章

  1. 使用LinkedList模拟一个堆栈或者队列数据结构

    使用LinkedList模拟一个堆栈或者队列数据结构. 堆栈:先进后出  如同一个杯子. 队列:先进先出  如同一个水管. import java.util.LinkedList; public cl ...

  2. C# 模拟一个处理消息队列的线程类 Message Queue

    // 模拟一个处理消息队列的类 class MessageHandler { // 消息队列 private Queue<string> messageQue = new Queue< ...

  3. java集合 collection-list-LinkedList 模拟一个堆栈或者队列数据结构。

    /* 使用LinkedList模拟一个堆栈或者队列数据结构. 堆栈:先进后出 如同一个杯子. 队列:先进先出 First in First out FIFO 如同一个水管. */ import jav ...

  4. Java LinkedList特有方法程序小解 && 使用LinkedList 模拟一个堆栈或者队列数据结构。

    package Collection; import java.util.LinkedList; /* LinkedList:特有的方法 addFirst()/addLast(); getFirst( ...

  5. 面试题:使用LinkedList来模拟一个堆栈或者队列数据结构

    请使用LinkedList来模拟一个堆栈或者队列数据结构. 堆栈:先进后出 First In Last Out  (FILO) 队列:先进先出 First In First Out  (FIFO) 我 ...

  6. java 使用LinkedList模拟一个堆栈或者队列数据结构

    近期在复习下java基础,看了下java基础,在看到集合时突然发现想起来曾经面试有一道笔试题:模拟一个堆栈或者队列数据结构,当时还没做出来,今天就写一下,首先得明确堆栈和队列的数据结构 堆栈:先进后出 ...

  7. C语言数据结构-链式队列的实现-初始化、销毁、清空、长度、队列头元素、插入、删除、显示操作

    1.数据结构-链式队列的实现-C语言 typedef struct QNode { int data; struct QNode *next; }QNode,*QueuePtr; typedef st ...

  8. LeetCode初级算法--数组01:只出现一次的数字

    LeetCode初级算法--数组01:只出现一次的数字 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn. ...

  9. LeetCode初级算法--字符串01:反转字符串

    LeetCode初级算法--字符串01:反转字符串 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.ne ...

  10. LeetCode初级算法--链表01:反转链表

    LeetCode初级算法--链表01:反转链表 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/ ...

随机推荐

  1. [转帖]linux 查看CPU 内存的信息

    https://bbs.huaweicloud.com/blogs/302929   [摘要] ECS信息规格:2vCPUs | 4GiB | kc1.large.2镜像:openEuler 20.0 ...

  2. [转帖] Linux命令拾遗-文本处理篇

    https://www.cnblogs.com/codelogs/p/16060413.html 简介# 这是Linux命令拾遗系列的第二篇,本篇主要介绍Linux中与文本处理相关的命令,如xargs ...

  3. Springboot数据库连接池的学习与了解

    背景 昨天学习总结了tomcat的http连接池和线程池相关的知识,总结的不是很完整, 自己知道的也比较少,总结的时候就在想tomcat针对client 端有连接池,并且通过NIO的机制, 以较少的t ...

  4. js中toFixed 并不是你想的那样进行四舍五入

    toFixed 的简单介绍 toFixed() 方法可把 Number 类型的数字通过四舍五入为指定小数位的字符串.(将数字类型转化为字符串类型) 也就是说toFixed只能够处理数字类型的. 字符串 ...

  5. vue3中mixins的使用

    vue3-mixins 在开发的过程中我们会遇见相同或者相似的逻辑代码. 可以通过vue的 mixin 功能抽离公共的业务逻辑, 然后通过impor再组件中引入.通过mixins注册进来. 这样我们就 ...

  6. PDF标准详解(一)——PDF文档结构

    已经很久没有写博客记录自己学到的一些东西了.但是在过去一年的时间中自己确实又学到了一些东西.一直攒着没有系统化成一篇篇的文章,所以今年的博客打算也是以去年学到的一系列内容为主.通过之前Vim系列教程的 ...

  7. TienChin 渠道管理-字典原理分析

    在上一节当中,我们使用到了字典来进行翻译我们的渠道类型等等字段,那么这一节我们就来分析一下字典的原理. 从代码方面先开始分析,我们先来看一下字典的定义,我们是在如下图当中编写了我们的渠道类型,使用,p ...

  8. 深度学习应用篇-计算机视觉-OCR光学字符识别[7]:OCR综述、常用CRNN识别方法、DBNet、CTPN检测方法等、评估指标、应用场景

    深度学习应用篇-计算机视觉-OCR光学字符识别[7]:OCR综述.常用CRNN识别方法.DBNet.CTPN检测方法等.评估指标.应用场景 1.OCR综述 OCR(Optical Character ...

  9. 驱动开发:内核MDL读写进程内存

    MDL内存读写是最常用的一种读写模式,通常需要附加到指定进程空间内然后调用内存拷贝得到对端内存中的数据,在调用结束后再将其空间释放掉,通过这种方式实现内存读写操作,此种模式的读写操作也是最推荐使用的相 ...

  10. Libevent [补档-2023-08-29]

    libevent的使用 8-1 安装 ​ 自己百度一下,安装它不是特别难,加油!!! 8-2 libevent介绍 ​ 它是一个开源库,用于处理网络和定时器等等事件.它提供了跨平台的API,能够在不同 ...