当前位置: 首页 > news >正文

【C++代码】用栈实现队列,用队列实现栈--代码随想录

  • 队列是先进先出,栈是先进后出。卡哥给了关于C++方向关于栈和队列的4个问题:

    • C++中stack 是容器么?

    • 使用的stack是属于哪个版本的STL?

    • 使用的STL中stack是如何实现的?

    • stack 提供迭代器来遍历stack空间么?

  • 首先大家要知道 栈和队列是STL(C++标准库)里面的两个数据结构。C++标准库是有多个版本的,要知道我们使用的STL是哪个版本,才能知道对应的栈和队列的实现原理。接下来介绍的栈和队列也是SGI STL里面的数据结构, 知道了使用版本,才知道对应的底层实现。来说一说栈,栈先进后出,如图所示:

    • 在这里插入图片描述

    • 栈提供push 和 pop 等等接口,所有元素必须符合先进后出规则,所以栈不提供走访功能,也不提供迭代器(iterator)。 不像是set 或者map 提供迭代器iterator来遍历所有元素。

  • 栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可插拔的(也就是说我们可以控制使用哪种容器来实现栈的功能)。所以STL中栈往往不被归类为容器,而被归类为container adapter(容器适配器)。从下图中可以看出,栈的内部结构,栈的底层实现可以是vector,deque,list 都是可以的, 主要就是数组和链表的底层实现

    • 在这里插入图片描述

    • 我们常用的SGI STL,如果没有指定底层实现的话,默认是以deque为缺省情况下栈的底层结构。deque是一个双向队列,只要封住一段,只开通另一端就可以实现栈的逻辑了。SGI STL中 队列底层实现缺省情况下一样使用deque实现的。栈的特性,对应的队列的情况是一样的。可以指定vector为栈的底层实现,初始化语句如下:

    • std::stack<int, std::vector<int> > third;  // 使用vector为底层容器的栈
      
  • 队列中先进先出的数据结构,同样不允许有遍历行为,不提供迭代器, SGI STL中队列一样是以deque为缺省情况下的底部结构。也可以指定list 为起底层实现,初始化queue的语句如下:

    • std::queue<int, std::list<int>> third; // 定义以list为底层容器的队列
      
    • 所以STL 队列也不被归类为容器,而被归类为container adapter( 容器适配器)。

题目:用栈实现队列

  • 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty),实现 MyQueue 类:

    • void push(int x) 将元素 x 推到队列的末尾

    • int pop() 从队列的开头移除并返回元素

    • int peek() 返回队列开头的元素

    • boolean empty() 如果队列为空,返回 true ;否则,返回 false

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

  • 在这里插入图片描述

题解
  • 将一个栈当作输入栈,用于压入 push 传入的数据;另一个栈当作输出栈,用于 pop 和 peek 操作。每次 pop 或 peek 时,若输出栈为空则将输入栈的全部数据依次弹出并压入输出栈,这样输出栈从栈顶往栈底的顺序就是队列从队首往队尾的顺序。

  • class MyQueue {
    private:stack<int> inStack,outStack;void in2out(){while(!inStack.empty()){outStack.push(inStack.top());inStack.pop();}}
    public:MyQueue() {}void push(int x) {inStack.push(x);}int pop() {if(outStack.empty()){in2out();}int res = outStack.top();outStack.pop();return res;}int peek() {if(outStack.empty()){in2out();}return outStack.top();} bool empty() {return inStack.empty() && outStack.empty();}
    };
    /*** Your MyQueue object will be instantiated and called as such:* MyQueue* obj = new MyQueue();* obj->push(x);* int param_2 = obj->pop();* int param_3 = obj->peek();* bool param_4 = obj->empty();*/
    

题目:用队列实现栈

  • 请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppopempty)。实现 MyStack 类:

    • void push(int x) 将元素 x 压入栈顶。

    • int pop() 移除并返回栈顶元素。

    • int top() 返回栈顶元素。

    • boolean empty() 如果栈是空的,返回 true ;否则,返回 false

  • 只能使用队列的基本操作 —— 也就是 push to backpeek/pop from frontsizeis empty 这些操作。所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

题解
  • 题目涉及到栈和队列两种数据结构。栈是一种后进先出的数据结构,元素从顶端入栈,然后从顶端出栈。队列是一种先进先出的数据结构,元素从后端入队,然后从前端出队。

  • 为了满足栈的特性,即最后入栈的元素最先出栈,在使用队列实现栈时,应满足队列前端的元素是最后入栈的元素。可以使用两个队列实现栈的操作,其中 queue1 用于存储栈内的元素,queue2 作为入栈操作的辅助队列。

  • 入栈操作时,首先将元素入队到 queue2 ,然后将 queue1 的全部元素依次出队并入队到 queue2 ,此时 queue2 的前端的元素即为新入栈的元素,再将 queue1 和 queue2 互换,则 queue1 的元素即为栈内的元素,queue1 的前端和后端分别对应栈顶和栈底。

  • 由于每次入栈操作都确保 queue1 的前端元素为栈顶元素,因此出栈操作和获得栈顶元素操作都可以简单实现。出栈操作只需要移除 queue1 的前端元素并返回即可,获得栈顶元素操作只需要获得 queue1 的前端元素并返回即可(不移除元素)。由于 queue1 用于存储栈内的元素,判断栈是否为空时,只需要判断 queue1 是否为空即可。

  • class MyStack {
    private:queue<int> queue1;queue<int> queue2;
    public:MyStack() {}void push(int x) {queue2.push(x);while(!queue1.empty()){//C++ 函数 std::queue::front() 返回对队列第一个元素的引用。 对队列执行 pop 操作后,该元素将被删除。queue2.push(queue1.front());queue1.pop();}swap(queue1,queue2);}int pop() {int pop_val = queue1.front();queue1.pop();return pop_val;}int top() {return queue1.front();}bool empty() {return queue1.empty();}
    };
    /*** Your MyStack object will be instantiated and called as such:* MyStack* obj = new MyStack();* obj->push(x);* int param_2 = obj->pop();* int param_3 = obj->top();* bool param_4 = obj->empty();*/
    
  • 时间复杂度:入栈操作 O(n),其余操作都是 O(1),其中 n 是栈内的元素个数。 入栈操作需要将 queue1 中的 n 个元素出队,并入队 n+1 个元素到 queue2,共有 2n+1 次操作,每次出队和入队操作的时间复杂度都是 O(1),因此入栈操作的时间复杂度是 O(n)。 出栈操作对应将 queue1 的前端元素出队,时间复杂度是 O(1)。 获得栈顶元素操作对应获得 queue1 的前端元素,时间复杂度是 O(1)。 判断栈是否为空操作只需要判断 queue1 是否为空,时间复杂度是 O(1)。

  • 空间复杂度:O(n),其中 n 是栈内的元素个数。需要使用两个队列存储栈内的元素。

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

  • class MyStack {
    private:// queue<int> queue1;// queue<int> queue2;queue<int> one_queue;
    public:MyStack() {}// void push(int x) {//     queue2.push(x);//     wile(!queue1.empty()){//         //C++ 函数 std::queue::front() 返回对队列第一个元素的引用。 对队列执行 pop 操作后,该元素将被删除。//         queue2.push(queue1.front());//         queue1.pop();//     }//     swap(queue1,queue2);// }void push(int x){int queue_size = one_queue.size();one_queue.push(x);for(int i=0;i<queue_size;i++){one_queue.push(one_queue.front());one_queue.pop();}}// int pop() {//     int pop_val = queue1.front();//     queue1.pop();//     return pop_val;// }int pop(){int top_val = one_queue.front();one_queue.pop();return top_val;}// int top() {//     return queue1.front();// }int top(){return one_queue.front();}// bool empty() {//     return queue1.empty();// }bool empty(){return one_queue.empty();}
    };
  • Queue 队列是一种设计用于在 FIFO(先进先出)上下文中操作的数据结构。 队列中的元素从 rear 端插入并从 front 端移除。Queue 队列类是容器适配器。 容器是保存相同类型数据的对象。 队列可以从不同的序列容器创建。 容器适配器不支持迭代器,因此我们不能将它们用于数据操作。 但是它们分别支持 push() 和 pop() 成员函数用于数据插入和删除。

  • 下面是来自 <queue> 头文件的 std::queue 的定义

    • template <class T, class Container = deque<T> > class queue;
      
    • T − 包含的元素的类型。T 可以替换为任何其他数据类型,包括用户定义的类型。Container − 基础容器对象的类型。

  • <queue> 中的函数

  • 方法说明
    queue::queue构造一个具有零个元素的空队列对象。
    queue::~queue通过释放容器内存来销毁队列。
    queue::back返回对队列最后一个元素的引用。
    queue::front返回对队列第一个元素的引用。
    queue::emplace在队列末尾构造并插入新元素。
    queue::empty测试队列是否为空。
    queue::pop删除队列的前面元素。
    queue::push在队列末尾插入新元素。
    queue::operator=通过替换旧内容将新内容分配给队列。
    queue::size返回队列中存在的元素总数。
    queue::swap将队列的内容与另一个队列的内容交换。
  • 堆栈是一种设计用于在 LIFO(后进先出)上下文中运行的数据结构。 在堆栈中,元素被插入以及仅从一端移除。Stack 类是容器适配器。 容器是保存相同类型数据的对象。 可以从不同的序列容器创建堆栈。如果未提供容器,则使用默认的 deque 容器。 容器适配器不支持迭代器,因此我们不能将它们用于数据操作。但是它们分别支持 push() 和 pop() 成员函数用于数据插入和删除。下面是来自 <stack> 头文件的 std::stack 定义

    • template <class T, class Container = deque<T> > class stack;
      
  • <stack> 中的成员函数

    • 方法说明
      stack::emplace在栈顶构造并插入新元素。
      stack::empty测试堆栈是否为空。
      stack::operator=通过替换旧内容将新内容分配给堆栈。
      stack::pop从堆栈中移除顶部元素。
      stack::push在栈顶插入新元素。
      stack::size返回堆栈中存在的元素总数。
      stack::swap将堆栈的内容与另一个堆栈的内容交换。
      stack::top返回对栈顶元素的引用。

相关文章:

【C++代码】用栈实现队列,用队列实现栈--代码随想录

队列是先进先出&#xff0c;栈是先进后出。卡哥给了关于C方向关于栈和队列的4个问题&#xff1a; C中stack 是容器么&#xff1f; 使用的stack是属于哪个版本的STL&#xff1f; 使用的STL中stack是如何实现的&#xff1f; stack 提供迭代器来遍历stack空间么&#xff1f; …...

肖sir__linux详解__001

linux详解: 1、ifconfig 查看ip地址 2、6版本&#xff1a;防火墙的命令&#xff1a; service iptables status 查看防火墙状态 service iptables statrt 开启防火墙 service iptables stop 关闭防火墙 service iptables restart 重启防火墙状态 7版本&#xff1a; systemctl s…...

【Android Framework系列】第12章 RecycleView相关原理及四级缓存策略分析

1 RecyclerView简介 RecyclerView是一款非常强大的widget&#xff0c;它可以帮助您灵活地显示列表数据。当我开始学习 RecyclerView的时候&#xff0c;我发现对于复杂的列表界面有很多资源可以参考&#xff0c;但是对于简单的列表展现就鲜有可参考的资源了。虽然RecyclerView的…...

P1886 滑动窗口 /【模板】(双端队列)+双端队列用法

例题 有一个长为 n 的序列 a&#xff0c;以及一个大小为 k 的窗口。现在这个从左边开始向右滑动&#xff0c;每次滑动一个单位&#xff0c;求出每次滑动后窗口中的最大值和最小值。 例如&#xff1a; The array is [1,3,−1,−3,5,3,6,7],and k3。 输入格式 输入一共有两行…...

网络渗透day6-面试01

&#x1f609; 和渗透测试相关的面试问题。 介绍 如果您想自学网络渗透&#xff0c;有许多在线平台和资源可以帮助您获得相关的知识和技能。以下是一些受欢迎的自学网络渗透的平台和资源&#xff1a; Hack The Box: Hack The Box&#xff08;HTB&#xff09;是一个受欢迎的平…...

Docker 及 Docker Compose 安装指南

Docker 是一个开源的容器化平台&#xff0c;可以帮助我们快速构建、打包和运行应用程序。而 Docker Compose 则是用于管理多个容器应用的工具&#xff0c;可以轻松定义和管理多个容器之间的关系。现在&#xff0c;让我们开始安装过程吧&#xff01; docker 安装 apt安装 sudo…...

Gitlab创建一个空项目

1. 创建项目 Project slug是访问地址的后缀&#xff0c;跟前边的ProjectUrl拼在一起&#xff0c;就是此项目的首页地址&#xff1b; Visibility Level选择默认私有即可&#xff0c;选择内部或者公开&#xff0c;就会暴露代码。 勾选Readme选项&#xff0c;这样项目内默认会带…...

C语言-内存分布(STM32内存分析)

C/C内存分布 一、内存组成二、静态区域文本段 &#xff08;Text / 只读区域 RO&#xff09;已初始化读写数据段&#xff08;RW data -- Initialized Data Segment&#xff09;未初始化数据段&#xff08;BSS -- Block Started by Symbol&#xff09; 三、动态区域堆&#xff08…...

Linux上配置NAT

Linux系统上实现NAT上网是一个挑战性的任务&#xff0c;需要对操作系统进行合理的配置。本文将概述在Linux上实现NAT上网&#xff0c;并给出相应的工作步骤。 NAT&#xff0c;即Network Address Translation&#xff0c;是一种网络部署技术&#xff0c;可以在peivate network&…...

springboot实现简单的消息对话

目录 一、前言 二、实战步骤 步骤 1&#xff1a; 步骤 2&#xff1a; 步骤 3&#xff1a; 步骤 4&#xff1a; 一、前言 要在Spring Boot项目中实现消息对话&#xff0c;你可以使用WebSocket技术。WebSocket是一种在客户端和服务器之间提供实时双向通信的协议。 二、实…...

「Tech初见」Linux驱动之blkdev

目录 一、Motivation二、SolutionS1 - 块设备驱动框架&#xff08;1&#xff09;注册块设备&#xff08;2&#xff09;注销块设备&#xff08;3&#xff09;申请 gendisk&#xff08;4&#xff09;删除 gendisk&#xff08;5&#xff09;将 gendisk 加入 kernel&#xff08;6&a…...

ssh配置(二、登录服务器)

一. 登录 linux 服务器的两种方式 使用 ssh用户名密码 的方式登录&#xff0c;但这种方式不安全&#xff0c;密码太简单容易被暴力破解&#xff0c;密码太复杂又不容易记。使用 ssh公私钥 的方式登录。 以上两种方式都可以在图形化软件工具中配置&#xff0c;例如 finalshell…...

pytorch异常——RuntimeError:Given groups=1, weight of size..., expected of...

文章目录 省流异常报错异常截图异常代码原因解释修正代码执行结果 省流 nn.Conv2d 需要的输入张量格式为 (batch_size, channels, height, width)&#xff0c;但您的示例输入张量 x 是 (batch_size, height, width, channels)。因此&#xff0c;需要对输入张量进行转置。 注意…...

【FPGA项目】沙盘演练——基础版报文收发

​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ 第1个虚拟项目 前言 点灯开启了我们的FPGA之路&#xff0c;那么我们来继续沙盘演练。 用一个虚拟项目&#xff0c;来入门练习&#xff0c;以此步入数字逻辑的…...

【C++技能树】继承概念与解析

Halo&#xff0c;这里是Ppeua。平时主要更新C&#xff0c;数据结构算法&#xff0c;Linux与ROS…感兴趣就关注我bua&#xff01; 继承 0. 继承概念0.1 继承访问限定符 1. 基类和派生类对象赋值兼容转换2. 继承中的作用域3. 派生类中的默认成员函数4.友元5.继承中的静态成员6.菱…...

计算机网络 第二节

目录 一&#xff0c;计算机网络的分类 1.按照覆盖范围分 2.按照所属用途分 二&#xff0c;计算机网络逻辑组成部分 1.核心部分 &#xff08;通信子网&#xff09; 1.1电路交换 1.2 分组交换 两种方式的特点 重点 2.边缘部分 &#xff08;资源子网&#xff09; 进程通信的方…...

无涯教程-机器学习 - 矩阵图函数

相关性是有关两个变量之间变化的指示&#xff0c;在前面的章节中&#xff0c;无涯教程讨论了Pearson的相关系数以及相关的重要性&#xff0c;可以绘制相关矩阵以显示哪个变量相对于另一个变量具有较高或较低的相关性。 在以下示例中&#xff0c;Python脚本将为Pima印度糖尿病数…...

Redis 高可用与集群

Redis 高可用与集群 虽然 Redis 可以实现单机的数据持久化&#xff0c;但无论是 RDB 也好或者 AOF 也好&#xff0c;都解决 不了单点宕机问题&#xff0c;即一旦单台 redis 服务器本身出现系统故障、硬件故障等问题后&#xff0c; 就会直接造成数据的丢失&#xff0c;因此需要…...

修改文件名后Git仓上面并没有修改

场景&#xff1a; 我在本地将文件夹名称由Group → group ,执行git push 后&#xff0c;远程分支上的文件名称并没有修改。 原因&#xff1a; 是我绕过了git 直接使用了系统的重命名操作。 在 Git 中&#xff0c;对于已经存在的文件或文件夹进行大小写重命名是一个敏感的操作…...

Linux 信号

目录 基本概念信号的分类可靠信号与不可靠信号实时信号与非实时信号 常见信号与默认行为进程对信号的处理signal()函数sigaction()函数 向进程发送信号kill()函数raise() alarm()和pause()函数alarm()函数pause()函数 信号集初始化信号集测试信号是否在信号集中 获取信号的描述…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...

热烈祝贺埃文科技正式加入可信数据空间发展联盟

2025年4月29日&#xff0c;在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上&#xff0c;可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞&#xff0c;强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...

node.js的初步学习

那什么是node.js呢&#xff1f; 和JavaScript又是什么关系呢&#xff1f; node.js 提供了 JavaScript的运行环境。当JavaScript作为后端开发语言来说&#xff0c; 需要在node.js的环境上进行当JavaScript作为前端开发语言来说&#xff0c;需要在浏览器的环境上进行 Node.js 可…...

智警杯备赛--excel模块

数据透视与图表制作 创建步骤 创建 1.在Excel的插入或者数据标签页下找到数据透视表的按钮 2.将数据放进“请选择单元格区域“中&#xff0c;点击确定 这是最终结果&#xff0c;但是由于环境启不了&#xff0c;这里用的是自己的excel&#xff0c;真实的环境中的excel根据实训…...

Pandas 可视化集成:数据科学家的高效绘图指南

为什么选择 Pandas 进行数据可视化&#xff1f; 在数据科学和分析领域&#xff0c;可视化是理解数据、发现模式和传达见解的关键步骤。Python 生态系统提供了多种可视化工具&#xff0c;如 Matplotlib、Seaborn、Plotly 等&#xff0c;但 Pandas 内置的可视化功能因其与数据结…...