【C++】stack queue的介绍使用以及模拟实现

news2024/11/24 18:40:55

目录

01.容器适配器

02.栈(stack)

1.stack的介绍

2.stack的使用

3.stack的模拟实现

03.队列(queue)

1.queue的介绍:

2.queue的使用

3.queue的模拟实现

04.双端队列(deque)

1.介绍

2.优缺点

3.为什么选择deque


01.容器适配器

适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。

就好比由于国内外电器插头标准不同,出国时就需要携带插头转换器,使得国内的电器插头可以和外国的插座兼容。插头转换器就是一种适配器。

C++中的容器适配器是一种特殊的容器,它们提供了特定的接口和功能,使其在特定的使用场景下更加方便和高效。C++标准库提供了三种主要的容器适配器:栈(stack)、队列(queue)和优先队列(priority_queue)。这些适配器都是基于其他基本的容器实现的,栈和队列通常基于deque(双端队列)实现,而优先队列通常基于vector实现。

02.栈(stack)

1.stack的介绍

这是cplusplus网站上对stack的文档介绍:stack的文档介绍

  1. stack 是一种容器适配器:它专门用于后进先出(LIFO)操作,例如压入和弹出元素。stack 实现了一种简化的接口,只允许在容器的一端进行元素的插入和提取操作。

  2. 底层容器的封装:stack 封装了一个底层容器,该容器负责实际存储元素。stack 提供了一组特定的成员函数,用于访问其底层容器的元素,并将特定类作为其底层容器,元素在容器的尾部(栈顶)进行压入和弹出操作。

  3. 底层容器的要求:stack 的底层容器可以是任何标准的容器类模板或者其他特定的容器类。底层容器需要支持以下操作:判空操作(empty)、获取尾部元素操作(back)、尾部插入元素操作(push_back)和尾部删除元素操作(pop_back)。

  4. 支持的容器:标准容器 vector、deque、list 都符合 stack 底层容器的要求。默认情况下,如果没有为 stack 指定特定的底层容器,stack 会使用 deque 作为默认的底层容器。                                                      

2.stack的使用

构造函数:

  • stack(): 创建一个空栈。
  • stack(const stack& other): 复制构造函数,根据另一个栈创建一个新的栈。

赋值和交换:

  • operator=: 赋值操作符,用另一个栈的内容替换当前栈的内容。
  • swap(stack& other) noexcept: 交换两个栈的内容。

容量查询:

  • empty() const noexcept: 判断栈是否为空。
  • size() const noexcept: 返回栈中元素的数量。

访问元素:

  • top() const: 返回栈顶元素的引用。

修改容器

  • push(const T& value): 将元素压入栈顶。
  • emplace(Args&&... args): 在栈顶构造一个新元素。
  • pop(): 弹出栈顶元素。

以下为代码示例:

#include <iostream>
#include <stack>

int main() {
    // 定义一个存储整数的栈
    std::stack<int> myStack;

    // 向栈中压入一些元素
    myStack.push(10);
    myStack.push(20);
    myStack.push(30);

    // 访问栈顶元素
    std::cout << "栈顶元素: " << myStack.top() << std::endl;

    // 弹出栈顶元素
    myStack.pop();

    // 再次访问栈顶元素
    std::cout << "弹出后的栈顶元素: " << myStack.top() << std::endl;

    // 判断栈是否为空
    if (myStack.empty()) {
        std::cout << "栈为空" << std::endl;
    } else {
        std::cout << "栈不为空,大小为: " << myStack.size() << std::endl;
    }

    return 0;
}

运行结果如下:

栈顶元素: 30
弹出后的栈顶元素: 20
栈不为空,大小为: 2

3.stack的模拟实现

从栈的接口可以看出,栈实际是一种特殊的vector,因此使用vector完全可以模拟实现stack。

#include<vector>
 
namespace my
 {
    template<class T>
    class stack
    {
    public:
        stack() {}
        void push(const T& x) {
            _c.push_back(x);
        }
        void pop() {
            _c.pop_back();
        }
        T& top() {
            return _c.back();
        }
        const T& top()const {
            return _c.back();
        }
        size_t size()const {
            return _c.size();
        }
        bool empty()const {
            return _c.empty();
        }
    private:
        std::vector<T> _c;
     };
 }

03.队列(queue)

1.queue的介绍:

queue的文档介绍

  1. 队列是一种容器适配器:队列容器适配器专门用于先进先出(FIFO)的上下文环境中操作。元素从队尾入队列,从队头出队列。

  2. 作为容器适配器的实现:队列作为容器适配器,封装了一个特定的底层容器类作为其内部实现。它提供了一组特定的成员函数,用于访问其元素。

  3. 底层容器的要求:队列的底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。底层容器至少需要支持以下操作:

    • empty(): 检测队列是否为空。
    • size(): 返回队列中有效元素的个数。
    • front(): 返回队头元素的引用。
    • back(): 返回队尾元素的引用。
    • push_back(): 在队尾入队列。
    • pop_front(): 在队头出队列。
  4. 支持的标准容器类:标准容器类 deque 和 list 都满足了这些要求。默认情况下,如果没有为队列指定底层容器类,则会使用标准容器 deque。

2.queue的使用

构造函数:

  • queue(): 创建一个空队列。
  • queue(const queue& other): 复制构造函数,根据另一个队列创建一个新的队列。

赋值和交换:

  • operator=: 赋值操作符,用另一个队列的内容替换当前队列的内容。
  • swap(queue& other) noexcept: 交换两个队列的内容。

容量查询:

  • empty() const noexcept: 判断队列是否为空。
  • size() const noexcept: 返回队列中元素的数量。

访问元素:

  • front() const: 返回队头元素的引用。
  • back() const: 返回队尾元素的引用。

修改容器:

  • push(const T& value): 将元素入队列。
  • emplace(Args&&... args): 在队尾构造一个新元素。
  • pop(): 出队列。

代码示例:

#include <iostream>
#include <queue>

int main() {
    // 定义一个存储整数的队列
    std::queue<int> myQueue;

    // 入队列
    myQueue.push(10);
    myQueue.push(20);
    myQueue.push(30);

    // 访问队头元素
    std::cout << "队头元素: " << myQueue.front() << std::endl;

    // 出队列
    myQueue.pop();

    // 再次访问队头元素
    std::cout << "出队后的队头元素: " << myQueue.front() << std::endl;

    // 判断队列是否为空
    if (myQueue.empty()) {
        std::cout << "队列为空" << std::endl;
    } else {
        std::cout << "队列不为空,大小为: " << myQueue.size() << std::endl;
    }

    return 0;
}

运行结果: 

队头元素: 10
出队后的队头元素: 20
队列不为空,大小为: 2

3.queue的模拟实现

因为queue的接口中存在头删和尾删,因此用vector来封装效率太低,因此可以借助list来实现:

#include <list>
 namespace my
 {
    template<class T>
    class queue
    {
    public:
        queue() {}
        void push(const T& x) {
            _c.push_back(x);
        }
        void pop() {
            _c.pop_front();
        }
        T& back() {
            return _c.back();
        }
        const T& back()const {
            return _c.back();
        }
        T& front() {
            return _c.front();
        }
        const T& front()const {
            return _c.front();
        }
        size_t size()const {
            return _c.size();
        }
        bool empty()const {
            return _c.empty();
        }
    private:
        std::list<T> _c;
    };
 }

04.双端队列(deque)

1.介绍

deque(双端队列):是一种双开口的“连续”空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率较高。

deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组

2.优缺点

与vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不 需要搬移大量的元素,因此其效率是必vector高的。

与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。

但是,deque有一个致命缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到 某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构 时,大多数情况下优先考虑vector和list,deque的应用并不多,而目前能看到的一个应用就是,STL用其作 为stackqueue的底层数据结构。

3.为什么选择deque

stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性结构,都可以作为stack的底层容器,vector和list都可以;queue是先进先出的特殊线性数据结构,只要具有push_back()和pop_front()操作的线性结构,都可以作为queue的底层容器,比如list。但是STL中对stack和queue默认选择deque作为其底层容器,主要是因为:

  • stack和queue不需要遍历(因此他们没有迭代器),只需要在固定的一端或者两端进行操作。
  • 在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的元素增长时,dequeue不仅效率高,而且内存使用率高

完美结合了deque的优点,并且规避了其缺点。

以上就是stack & queue的介绍说明了,欢迎在评论区留言,觉得这篇博客对你有帮助的可以点赞关注收藏支持一波喔~😉 

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

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

相关文章

LeetCode1017题:负二进制转换(原创)

【题目描述】 给你一个整数 n &#xff0c;以二进制字符串的形式返回该整数的 负二进制&#xff08;base -2&#xff09;表示。注意&#xff0c;除非字符串就是 "0"&#xff0c;否则返回的字符串中不能含有前导零。 示例 1&#xff1a; 输入&#xff1a;n 2 输出&…

深度学习-N维数组和访问元素

目录 N维数组访问元素 N维数组 N维数组是机器学习和神经网络的主要数据结构 访问元素 最后一个子区域中的::是跳的意思&#xff0c;这个区域说明的是从第一个元素&#xff08;即第一行第一列那个&#xff09;对行开始跳3下循环下去直到行结束、对列开始跳2下循环下去直到列…

springboot拦载器

1、拦载器 package com.Interceptor;import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;import javax.security.auth.login.Log…

如何快速申请SSL证书实现HTTPS访问?

申请SSL证书最简单的方法通常涉及以下几个步骤&#xff0c;尽量简化了操作流程和所需专业知识&#xff1a; 步骤一&#xff1a;选择适合的SSL证书类型 根据您的网站需求&#xff0c;选择最基础的域名验证型&#xff08;DV SSL&#xff09;证书&#xff0c;它通常只需验证域名所…

技术融合与创新大象机器人水星Mercury X1人形机器人案例研究!

引言 在科技迅速发展的当下&#xff0c;人形机器人正变得日益重要&#xff0c;其应用范围从工业自动化到服务业不断扩展。本文将通过Mercury X1大象人形机器人的案例&#xff0c;探讨如何利用尖端技术如大型语言模型&#xff08;LLM&#xff09;、同时定位与映射&#xff08;SL…

雅思(IELTS)优秀小作文分享

IELTS优秀小作文分享 柱状图 本篇范文个人评分是8分或者8.5分&#xff0c;属于能找到的最优质的范文了 题目如下: The two sets of bar charts illustrate the amount of time that teenagers (boys, girls, and all) in the UK spend chatting online and playing game c…

2024 java使用Graceful Response,告别自己去封装响应,可以接收数据异常,快看我这一篇,足够你用!

参考官网手册地址&#xff1a;快速入门 | Docs 一、导入依赖&#xff08;根据springboot查看对应依赖版本&#xff09; <!-- Graceful --><dependency><groupId>com.feiniaojin</groupId><artifactId>graceful-response</artifactId&g…

GaussDB数据库事务管理

一、引言 事务管理是数据库系统中至关重要的一部分&#xff0c;它确保了数据库的一致性和可靠性。在GaussDB数据库中&#xff0c;事务管理不仅遵循传统的ACID特性&#xff0c;还提供了一些高级功能。本文将深入探讨GaussDB数据库事务管理的各个方面。 二、事务的基本概念 2.1…

CSS Position定位(详解网页中的定位属性)

目录 一、Position介绍 1.概念 2.特点 3.作用 4.应用 二、Position用法 1.position属性 2.static定位 3.fixed定位 4.relative定位 5.absolute定位 6.sticky定位 7.重叠的元素 三、CSS定位属性 四、总结 一、Position介绍 1.概念 文档流&#xff08;Document Fl…

C++ 之 string类的模拟实现

这学习我有三不学 昨天不学&#xff0c;因为昨天是个过去 明天不学&#xff0c;因为明天还是个未知数 今天不学&#xff0c;因为我们要活在当下&#xff0c;我就是玩嘿嘿~ –❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀-正文开始-❀–❀–…

springboot笔记一:idea社区版本创建springboot项目的方式

社区idea 手动maven 创建springboot项目 创建之后修改pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:sc…

Microsoft Edge浏览器:高效、简洁、个性化的网页浏览体验

Microsoft Edge是微软公司推出的一款网络浏览器&#xff0c;它是基于Chromium开源项目开发的&#xff0c;因此与Google Chrome有很多相似之处。以下是一些使用Microsoft Edge的心得体会&#xff1a; 1. 界面简洁&#xff1a;Microsoft Edge的界面设计非常简洁&#xff0c;用户…

R语言--图形绘制

一&#xff0c;绘制简单图形 c1<- c(10,20,30,40,50) c2<-c(2,7,15,40,50) plot(c1,c2,typeb) 具体参数请参考R语言中的绘图技巧1&#xff1a;plot()函数参数汇总_r语言plot参数设置-CSDN博客 c1<- c(10,20,30,40,50) c2<-c(2,7,15,40,50) plot(c1,c2,typeb,col#…

【北京迅为】《iTOP龙芯2K1000开发指南》-第四部分 ubuntu开发环境搭建

龙芯2K1000处理器集成2个64位GS264处理器核&#xff0c;主频1GHz&#xff0c;以及各种系统IO接口&#xff0c;集高性能与高配置于一身。支持4G模块、GPS模块、千兆以太网、16GB固态硬盘、双路UART、四路USB、WIFI蓝牙二合一模块、MiniPCIE等接口、双路CAN总线、RS485总线&#…

信息化还是数字化?

从 PC 互联网到移动互联网&#xff0c;再到物联网和最近流行的人工智能&#xff0c;科技的进步正在不断地改变着我们的生活和工作方式。这个过程实际上也是信息化和数字化的演进过程&#xff0c;许多人会问那信息化和数字化有啥区别&#xff1f;作为企业&#xff0c;如何在浪潮…

机器人操作系统ROS2学习—编译工作空间colcon build报错问题

在ROS2中&#xff0c;工作空间创建完成后&#xff0c;会经常需要编译工作空间。在工作空间dev_ws 下打开一个终端&#xff0c;通过指令Colcon build来编译工作空间。 1、这个过程有可能会出现如下错误: "colconbuild:Duplicate package names not supported" 根据…

openstack-自动化部署 9

所使用的kolla-ansible版本文档&#xff1a; Quick Start — kolla-ansible 14.10.1.dev21 documentation (openstack.org) 创建一个新的虚拟机 配置主机 安装docker 拉取openstack所需的组件镜像 安装ansible 配置ansible 启用lvm需要将另一个磁盘打成pv&#xff0c;以创建成…

如何与卫星影像叠加导出?

让每个人都有自己的地图&#xff01; 水经微图&#xff08;以下简称“微图”&#xff09;网页版&#xff0c;无需安装就可以绘制地图&#xff0c;得到了越来越多用户的亲睐。 但是&#xff0c;当我们千辛万苦绘制出来的地图&#xff0c;该如何与卫星影像叠加导出呢&#xff1…

【redis】Redis数据类型(一)——String类型(包含redis通用命令)

目录 Redis通用命令String类型常用的操作命令一些特殊命令详解setnx示例使用 setrange示例 mset示例 msetnx示例 append示例 getset示例 incr示例使用1.计数器2.限速器 bitcount示例使用&#xff1a;使用 bitmap 实现用户上线次数统计性能 String类型String类型简介String类型的…

Akamai 分布式“云+边缘”,打造下一代数字化基座

当下&#xff0c;数字化基础设施正逐步向分布式部署演化&#xff0c;云计算与边缘计算正在成为两大技术支柱。Gartner 数据显示&#xff0c;云服务占 IT 整体支出比例连年上涨&#xff0c;在过去一年已增长至12.1%&#xff1b;IDC 报告显示&#xff0c;截至2021年已有超过500亿…