用队列实现栈,用栈实现队列

有两个地方会讨论到栈,一个是程序运行的栈空间,一个是数据结构中的栈,本文中讨论的是后者。

栈是一个先入后出,后入先出的数据结构,只能操作栈顶。栈有两个操作,push 和 pop,push 是向将数据压栈,pop 是将数据出栈。栈还有一个操作 top,这个操作可以查看栈顶的元素,不会出栈。

队列是一种先入先出,后入后出的数据结构。

 

 1 用队列实现栈

leetcode 链接:

用队列实现栈

用队列实现栈,队列先入先出以及栈先入后出的语义不能改变。关键是怎么在压栈的时候,将数据放到队列头,这就需要两个队列进行配合。

两个队列配合的方式有两种,这两种方式均可以解答这个问题:

(1)入栈的时候进行元素移动

① 两个队列,始终保持一个队列是空的,假设是队列 A,压栈的时候,将元素放入这个队列。这样最后入队的放到了队列头,所以下次出栈的时候就是第一个出队的。满足先进后出,后进先出的要求,也就是栈的语义。

② 然后将另一个队列(假设是队列 B)里边的元素都移动到这个队列中。

这样,元素都移动到了队列 A 中,队列 B 成为了空队列。下一个元素入队的时候,将元素入队到队列 B,将元素 A 中的元素移动到 B 中。以此类推。

每个元素入队的时候都做这个操作。

第一个元素 10:入队 A,B 中没有元素不需要操作

第二个元素 20:入队 B,A 中的 10 移动到 B

第 3 个元素 30: 入队 A,B 中元素移动到 A

(2)出栈的时候进行元素移动

① 压栈的时候将元素入队到有元素的这个队列里边

② 出栈的时候将元素移动到另一个队列中,同时进行判断,当队列剩余 1 个元素的时候,这个元素就是出栈的元素,不用移动到另一个队列中了。

方法 1 的主要逻辑在 push() 函数中实现;方法 2 的主要逻辑在 top() 和 pop() 函数中都要实现。

两个方法都可以通过两个队列来实现,也可以通过一个队列也是可以实现的。

1.1 入队时处理,双队列

class MyStack {
public:MyStack() {}void push(int x) {if (q_master_.empty()) {q_master_.push(x);while (!q_slave_.empty()) {q_master_.push(q_slave_.front());q_slave_.pop();}} else {q_slave_.push(x);while (!q_master_.empty()) {q_slave_.push(q_master_.front());q_master_.pop();}}}int pop() {if (!q_master_.empty()) {int data = q_master_.front();q_master_.pop();return data;} else {int data = q_slave_.front();q_slave_.pop();return data;}}int top() {if (!q_master_.empty()) {return q_master_.front();} else {return q_slave_.front();}}bool empty() {return q_master_.empty() && q_slave_.empty();}private:std::queue<int> q_master_;std::queue<int> q_slave_;
};

1.2 入队时操作,单队列

关键是 push() 函数中的操作,将元素入队之后,然后将新元素之外的元素出队,再重新入队。这样保证了新入队的元素移动到了队列头的位置,下次出栈的时候直接出队就可以。

class MyStack {
public:MyStack() {}void push(int x) {q_.push(x);int size = q_.size();for (int i = 0; i < size - 1; i++) {q_.push(q_.front());q_.pop();}}int pop() {int data = q_.front();q_.pop();return data;}int top() {return q_.front();}bool empty() {return q_.empty();}private:std::queue<int> q_;
};

1.3 出队时操作,双队列

class MyStack {
public:MyStack() {}void push(int x) {if (!q_master_.empty()) {q_master_.push(x);} else {q_slave_.push(x);}}int pop() {if (!q_master_.empty()) {int size = q_master_.size();for (int i = 0; i < size - 1; i++) {q_slave_.push(q_master_.front());q_master_.pop();}int data = q_master_.front();q_master_.pop();return data;} else {int size = q_slave_.size();for (int i = 0; i < size - 1; i++) {q_master_.push(q_slave_.front());q_slave_.pop();}int data = q_slave_.front();q_slave_.pop();return data;}}int top() {if (!q_master_.empty()) {int size = q_master_.size();for (int i = 0; i < size - 1; i++) {q_slave_.push(q_master_.front());q_master_.pop();}int data = q_master_.front();q_master_.pop();q_slave_.push(data);return data;} else {int size = q_slave_.size();for (int i = 0; i < size - 1; i++) {q_master_.push(q_slave_.front());q_slave_.pop();}int data = q_slave_.front();q_slave_.pop();q_master_.push(data);return data;}}bool empty() {return q_master_.empty() && q_slave_.empty();}private:std::queue<int> q_master_;std::queue<int> q_slave_;
};

1.4 出队时操作,单队列

class MyStack {
public:MyStack() {}void push(int x) {q_.push(x);}int pop() {int size = q_.size();for (int i = 0; i < size - 1; i++) {q_.push(q_.front());q_.pop();}int data = q_.front();q_.pop();return data;}int top() {int size = q_.size();for (int i = 0; i < size - 1; i++) {q_.push(q_.front());q_.pop();}int data = q_.front();q_.pop();q_.push(data);return data;}bool empty() {return q_.empty();}private:std::queue<int> q_;
};

2 用栈实现队列

leetcode 链接:

用栈实现队列

用栈实现队列,需要在出队的时候进行操作。在入队的时候进行操作,算法不好实现,不像队列中的元素,比如元素顺序是 E1、E2、E3、E4、E5,那么元素在移动之后还是这样的顺序,移动多次之后还是保持这样的顺序。但是对于栈来说,每移动一次就会导致顺序翻转,所以在入队的时候进行操作的算法不好实现。

使用栈实现队列,需要使用两个栈。只使用一个栈,算法也不好实现。

两个栈 A 和 B,在入队的时候只往 A 压栈,出队的时候只从 B 出栈。当 B 是空的时候,那么将 A 中所有的元素都移动到 B。

class MyQueue {
public:MyQueue() {}void push(int x) {s_in_.push(x);}int pop() {if (s_out_.empty()) {while (!s_in_.empty()) {s_out_.push(s_in_.top());s_in_.pop();}}int ret = s_out_.top();s_out_.pop();return ret;}int peek() {if (s_out_.empty()) {while (!s_in_.empty()) {s_out_.push(s_in_.top());s_in_.pop();}}return s_out_.top();}bool empty() {return s_out_.empty() && s_in_.empty();}private:std::stack<int> s_in_;std::stack<int> s_out_;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/15113.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电脑如何远程监控?如何远程监控电脑屏幕?

远程监控是指通过网络技术和远程视频传输技术&#xff0c;实现对某一特定区域、设备或场景进行远程实时监测、管理、控制的一种技术手段。 它将视频传输、图像采集、数据存储和远程操作等多种技术相结合&#xff0c;能够在任意时间、任意地点实现对被监测对象的远程监控。 远程…

在Windows系统服务器上安装Node.js的步骤

在windows操作系统中&#xff0c;可以使用命令行&#xff08;CMD&#xff09;安装Node.js。 【第一步】下载Node.js安装包 在官网https://nodejs.cn/download下载安装包&#xff0c;以 64位 Windows 安装包为例。 【第二步】将Node.js安装包上传到服务器 将安装包上传到指定…

基于Docker Compose部署One-API的详细指南

部署One-API的详细指南 前言 one-api是一个开源项目(https://github.com/songquanpeng/one-api)&#xff0c;旨在简化API的开发与管理过程。这个项目提供了一个全面的解决方案&#xff0c;特别适用于需要高效管理API接口的开发者和团队。以下是该项目的一些核心特点和功能&am…

IO模型:同步阻塞、同步非阻塞、同步多路复用、异步非阻塞

目录 stream和channel对比 同步、异步、阻塞、非阻塞 线程读取数据的过程 同步阻塞IO 同步非阻塞IO 同步IO多路复用 异步IO 优缺点对比 stream和channel对比 stream不会自动缓冲数据&#xff0c;channel会利用系统提供的发送缓冲区、接收缓冲区。stream仅支持阻塞API&am…

轻松拿捏C语言——【字符函数】字符分类函数、字符转换函数

&#x1f970;欢迎关注 轻松拿捏C语言系列&#xff0c;来和 小哇 一起进步&#xff01;✊ &#x1f308;感谢大家的阅读、点赞、收藏和关注&#x1f495; &#x1f339;如有问题&#xff0c;欢迎指正 感谢 目录&#x1f451; 一、字符分类函数&#x1f319; 二、字符转换函数…

hive3从入门到精通(二)

第15章:Hive SQL Join连接操作 15-1.Hive Join语法规则 join分类 在Hive中&#xff0c;当下版本3.1.2总共支持6种join语法。分别是&#xff1a; inner join&#xff08;内连接&#xff09;left join&#xff08;左连接&#xff09;right join&#xff08;右连接&#xff09;…

Python学习——— tupple

Python 中的数据结构是通过某种方式组织在一起的数据元素的集合&#xff0c;这些数据元素可以是数字、字符、甚至可以是其他数据结构 在 Python 中&#xff0c;最基本的数据结构是序列&#xff08;列表和元组&#xff09;&#xff0c;序列中的每个元素都有一个序号&#xff08;…

力扣HOT100 - 136. 只出现一次的数字

解题思路&#xff1a; class Solution {public int singleNumber(int[] nums) {int single 0;for (int num : nums) {single ^ num;}return single;} }

基于卷积神经网络的交通标志识别(pytorch,opencv,yolov5)

文章目录 数据集介绍&#xff1a;resnet18模型代码加载数据集&#xff08;Dataset与Dataloader&#xff09;模型训练训练准确率及损失函数&#xff1a;resnet18交通标志分类源码yolov5检测与识别&#xff08;交通标志&#xff09; 本文共包含两部分&#xff0c; 第一部分是用re…

回溯算法06(总结+leetcode332,51,37)

参考资料&#xff1a; https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E6%80%BB%E7%BB%93.html 力扣这三题暂时不在本篇笔记中贴代码了&#xff0c;有兴趣的可参考332.重新安排形成、N皇后、解数独 总结&#xff1a; 画树形图分析题目 用途&#xff1a;回溯算法是用 递归实现…

C++学习笔记(21)——继承

目录 1. 继承的概念及定义1.1 继承的概念1.2 继承定义1.2.1 定义格式1.2.2 继承关系和访问限定符1.2.3 继承基类成员访问方式的变化 继承的概念总结&#xff1a; 2. 基类和派生类对象赋值转换3.继承中的作用域4.派生类的默认成员函数知识点&#xff1a;派生类中6个默认成员函数…

win11 wsl ubuntu24.04

win11 wsl ubuntu24.04 一&#xff1a;开启Hyper-V二&#xff1a;安装wsl三&#xff1a;安装ubuntu24.04三&#xff1a;桥接模式&#xff0c;固定IP四&#xff1a;U盘使用五&#xff1a;wsl 从c盘迁移到其它盘参考资料 一&#xff1a;开启Hyper-V win11家庭版开启hyper-v 桌面…

Pytorch-01 框架简介

智能框架概述 人工智能框架是一种软件工具&#xff0c;用于帮助开发人员构建和训练人工智能模型。这些框架提供了各种功能&#xff0c;如定义神经网络结构、优化算法、自动求导等&#xff0c;使得开发人员可以更轻松地实现各种人工智能任务。通过使用人工智能框架&#xff0c;…

LangChain - Tool Calling 工具调用

文章目录 介绍组件1、ChatModel.bind_tools(...)2、AIMessage.tool_calls3、create_tool_calling_agent() 三、LangGraphwith_structured_output 四、结论 本文翻译整理自&#xff1a;Tool Calling with LangChain https://blog.langchain.dev/tool-calling-with-langchain/ TL…

汽车液态锂电池过充时,有怎样的表现,或者对电池有怎样的危害?

标签: 汽车液态锂电池过充的表现与危害; 电池过充; 汽车液态锂电池过充的表现与危害 液态锂电池在过充状态下,会出现一系列不良表现,并且对电池本身以及使用安全造成严重危害。以下是详细的分析: 1. 过充的表现 电压升高:在过充过程中,电池电压会超过其设计的最大电…

【MySQL精通之路】MySQL-环境变量

本节列出了MySQL直接或间接使用的环境变量。 其中大部分也可以在本手册的其他地方找到。 命令行上的选项优先于选项文件和环境变量中指定的值&#xff0c;选项文件中的值优先于环境变量中的值。 在许多情况下&#xff0c;最好使用配置文件而不是环境变量来修改MySQL的行为。…

虚拟机使用的是此版本 VMware Workstation 不支持的硬件版本。 模块“Upgrade”启动失败。 未能启动虚拟机。

问题&#xff1a; 虚拟机使用的是此版本 VMware Workstation 不支持的硬件版本。 模块“Upgrade”启动失败。 未能启动虚拟机。 分析&#xff1a; 该虚拟机环境之前使用的VMware版本与你所使用的VMware版本不一致。大概率你使用的是刚从别人电脑里拷过来的虚拟机环境。 解决&…

开发需要知道的敏捷开发理念

敏捷宣言和原则 敏捷软件开发宣言 敏捷软件开发宣言&#xff08;Agile Manifesto&#xff09;是敏捷开发方法的核心指导原则&#xff0c;由17位软件开发专家在2001年共同起草。该宣言强调了在软件开发过程中对某些价值观的优先级&#xff1a; 个体和互动高于流程和工具&#…

游戏后台开发技术全面解析

在这个数字时代&#xff0c;游戏产业已经成为全球最受欢迎的娱乐方式之一。从简单的手机游戏到复杂的大型多人在线角色扮演游戏&#xff08;MMORPG&#xff09;&#xff0c;游戏的世界正变得越来越丰富和多样化。而这一切的背后&#xff0c;都离不开强大的游戏后台技术支持。在…