【C++】stack和queue的使用及模拟实现(含deque的简单介绍)

文章目录

  • 前言
  • 一、deque的简单介绍
    • 1.引入deque的初衷
    • 2.deque的结构
    • 3.为什么选择deque作为stack和queue的底层默认容器
  • 二、stack
    • 1.stack的介绍
    • 2.stack的使用
    • 3.stack的模拟实现
  • 三、queue
    • 1.queue的介绍
    • 2.queue的使用
    • 3.queue的模拟实现


前言

一、deque的简单介绍(引入deque的初衷、deque的结构 以及 选择deque作为stack和queue的底层默认容器的原因)
二、stack和queue的使用及模拟实现


一、deque的简单介绍

1.引入deque的初衷

vector的优点是支持随机访问,缺点是插入删除元素的效率很低(除了尾插尾删);list的优点是在任意位置插入和删除元素的效率级高,缺点是不支持随机访问。
deque想要融合vector和list的优点弥补它们各自的缺陷,但是融合的并不完美。deque支持随机访问,但访问效率不如vector;而且还有一个致命缺陷:在中间位置的插入和删除效率极低,甚至低于vector;但deque在头尾插入和删除的效率特别高,优于vector,跟list效率同级别

2.deque的结构

deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。
在这里插入图片描述
deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,用一个指针数组map管理一段段小空间的起始地址,实际deque类似于一个动态的二维数组,其底层结构如下图所示:
在这里插入图片描述

3.为什么选择deque作为stack和queue的底层默认容器

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

  1. 高效的头尾操作 deque支持在两端以 O ( 1 ) O(1) O(1)时间复杂度进行插入和删除操作,这完美适配:

    • stack(后进先出):仅需尾部操作(push_back/pop_back)。
    • queue(先进先出):需要头部删除(pop_front)和尾部插入(push_back)。
  2. 内存管理的灵活性

    • 分段连续存储deque由多个固定大小的块组成,扩容时只需分配新块,不需要像vector那样复制整个数组到新位置,deque的扩容成本更低。
    • 避免内存浪费:与list的节点式存储相比,deque的分块结构更紧凑,空间利用率更好。
      list的底层节点不连续,小节点容易造成内存碎片,空间利用率低,缓存利用率低)

总结
虽然vector尾部操作高效,但头部操作低效,而且deque的扩容成本更低。 deque头尾操作性能跟list同级别,但综合性能优于list(缓存友好)。所以最终选择了queue作为stack和queue的底层默认容器。

二、stack

1.stack的介绍

栈是⼀种特殊的线性表,其只允许在固定的⼀端进行插入和删除元素操作。进行数据插入和删除操作的⼀端称为栈顶,另⼀端称为栈底。栈中的数据元素遵守后进先出的原则。

压栈(push):栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈(pop):栈的删除操作叫做出栈。出数据也在栈顶。

在这里插入图片描述

在这里插入图片描述
stake作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,stake提供一组特定的成员函数来访问其元素。
stack是一种后进先出的特殊线性数据结构,因此只要具push_back()和pop_back()操作的线性结构,都可以作为stack的底层容器,比如vector、list 和 deque都可以。默认情况下,如果没有为stake实例化指定容器类,则使用标准容器deque。

适配器是一种设计模式,该种模式是将一个类的接口转换成客户希望的另外一个接口。
虽然stack和queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为stack和队列只是对其他容器的接口进行了包装,STL中stack和queue默认使用deque作为其底层容器类。

2.stack的使用

在这里插入图片描述

函数说明接口说明
stack()构造空的栈
empty()检测stack是否为空
size()返回stack中元素的个数
top()返回栈顶元素的引用
push()将元素val压入stack中
pop()将stack中尾部的元素弹出
#include <iostream>
#include <stack>
using namespace std;int main()
{stack<int> sta;sta.push(9);sta.push(9);sta.push(6);sta.push(5);sta.push(2);sta.push(0);while (!sta.empty()){cout << sta.top() << ' ';sta.pop();}cout << endl;return 0;
}

在这里插入图片描述

3.stack的模拟实现

#include <deque>
using namespace std;
namespace zh
{template <class T, class Container = deque<T> >class stack{public:stack(){ }bool empty() const{return con.empty();}size_t size() const{return con.size();}T& top(){return con.back();}const T& top() const{return con.back();}void push(const T& val){con.push_back(val);}void pop(){con.pop_back();}void swap(stack& x){con.swap(x.con);}private:Container con;};
}

三、queue

1.queue的介绍

队列只允许在⼀端进行插入数据操作,在另⼀端进行删除数据操作的特殊线性表,队列具有先进先出的特性。

入队列:进行插入操作的⼀端称为队尾
出队列:进行删除操作的⼀端称为队头

在这里插入图片描述
在这里插入图片描述
queue作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。
queue是一种先进先出的特殊线性数据结构,因此只要具push_back和pop_front操作的线性结构,都可以作为queue的底层容器,比如list 和 deque都可以。默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque。

2.queue的使用

在这里插入图片描述

函数说明接口说明
queue()构造空的队列
empty()检测队列是否为空
size()返回队列中有效元素的个数
front()返回队头元素的引用
back()返回队尾元素的引用
push()在队尾将元素val入队列
pop()将队头元素出队列
#include <iostream>
#include <queue>
using namespace std;int main()
{queue<int> que;que.push(9);que.push(9);que.push(6);que.push(5);que.push(2);que.push(0);while (!que.empty()){cout << que.front() << ' ';que.pop();}cout << endl;return 0;
}

在这里插入图片描述

3.queue的模拟实现

#include <deque>
using namespace std;
namespace zh
{template <class T, class Container = deque<T> >class queue{public:queue(){ }bool empty() const{return con.empty();}size_t size() const{return con.size();}T& front(){return con.front();}const T& front() const{return con.front();}T& back(){return con.back();}const T& back() const{return con.back();}void push(const T& val){con.push_back(val);}void pop(){con.pop_front();}void swap(queue& x){con.swap(x.con);}private:Container con;};
}

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

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

相关文章

Leetcode 刷题笔记1 图论part01

图论的基础知识&#xff1a; 图的种类&#xff1a; 有向图&#xff08;边有方向&#xff09; 、 无向图&#xff08;边无方向&#xff09;、加权有向图&#xff08;边有方向和权值&#xff09; 度&#xff1a; 无向图中几条边连接该节点&#xff0c;该节点就有几度&#xff1…

《基于Workspace.java的Launcher3改造:HotSeat区域动态阻断文件夹生成机制》

1. 需求背景与技术挑战 在Android 13系统Launcher3定制化开发中&#xff0c;需实现禁止HotSeat区域创建文件夹的功能。原始逻辑中&#xff0c;当用户拖拽应用图标至HotSeat区域相邻图标时&#xff0c;会触发FolderIcon的实例化。本文将深入分析Launcher3的文件夹创建机制&…

重生之我在学Vue--第14天 Vue 3 国际化(i18n)实战指南

重生之我在学Vue–第14天 Vue 3 国际化(i18n)实战指南 文章目录 重生之我在学Vue--第14天 Vue 3 国际化(i18n)实战指南前言一、Vue I18n 核心配置1.1 基础环境搭建1.2 初始化配置1.3 全局挂载 二、多语言实现方案2.1 基础使用2.2 动态切换语言2.3 高级功能实现复数处理日期/货币…

开源PACS(dcm4che-arc-light)部署教程,源码方式

目录 文件清单下载地址安装概述OpenLDAP、Apache Directory StudioWildflydcm4che 安装部署MySQL源码编译dcm4cheedcm4chee-arc-light OpenLDAP安装ApacheDirectoryStudio安装配置WildFly服务器 部署完成 文件清单 下载地址 Apache directory studio - linkOpenLDAP - linkdcm…

java使用(Preference、Properties、XML、JSON)实现处理(读写)配置信息或者用户首选项的方式的代码示例和表格对比

在Java应用程序中&#xff0c;处理应用首选项&#xff08;preferences&#xff09;有多种方法&#xff0c;包括使用java.util.prefs.Preferences类、属性文件&#xff08;如.properties文件&#xff09;、XML文件和JSON文件。下面是每种方法的详细说明和代码示例&#xff0c;最…

工作记录 2017-02-04

工作记录 2017-02-04 序号 工作 相关人员 1 修改邮件上的问题。 更新RD服务器。 郝 更新的问题 1、DataExport的设置中去掉了ListPayors&#xff0c;见DataExport\bin\dataexport.xml 2、“IPA/Group Name” 改为 “Insurance Name”。 3、修改了Payment Posted的E…

dataframe数据形式操作中的diff和shift函数区别与对比

问题分析 从错误日志中可以看到&#xff0c;代码在 report_services.py 的 gnss_monthly_report 函数中出现了 ValueError&#xff0c;具体错误信息是&#xff1a; ValueError: either both or neither of x and y should be given这个错误发生在以下代码行&#xff1a; rep…

C语言动态内存管理(下)

欢迎拜访&#xff1a;雾里看山-CSDN博客 本篇主题&#xff1a;C语言动态内存管理(下) 发布时间&#xff1a;2025.3.18 隶属专栏&#xff1a;C语言 目录 动态内存常见错误内存泄漏&#xff08;Memory Leak&#xff09;典型场景后果解决方案 悬挂指针&#xff08;Dangling Pointe…

Vue:Vue2和Vue3创建项目的几种常用方式以及区别

前言 Vue.js 和 Element UI 都是用 JavaScript 编写的。 1、Vue.js 是一个渐进式 JavaScript 框架。2、Element UI 是基于 Vue.js 的组件库。3、JavaScript 是这两个项目的主要编程语言。 而Element Plus是基于TypeScript开发的。 一、Vue2 1、基于vuecli工具创建 vue2 …

机器人曲面跟踪Surface-Tracking

定义 机器人曲面跟踪&#xff08;Surface-Tracking&#xff09;是指机器人通过实时感知工件曲面的三维形貌&#xff0c;动态调整运动轨迹和位姿&#xff0c;以精确跟随曲面进行加工&#xff08;如打磨、抛光、喷涂等&#xff09;的技术。 力 - 位姿协同控制 力控模式&#xff…

网络安全运维应急响应与溯源分析实战案例

在日常运维过程中&#xff0c;网络安全事件时有发生&#xff0c;快速响应和精准溯源是保障业务稳定运行的关键。本文将通过一个实际案例&#xff0c;详细解析从发现问题到溯源定位&#xff0c;再到最终解决的完整流程。 目录 一、事件背景 二、事件发现 1. 监控告警触发 2…

【AVRCP】蓝牙协议栈深度解析:AVCTP互操作性核心机制与实现细节

目录 一、事务标签&#xff08;Transaction Label&#xff09;机制 1.1 事务标签核心规则 1.2 事务标签作用域与并发性 1.3 实现建议与陷阱规避 1.4 协议设计思考 1.5 调试与验证 二、消息分片&#xff08;Fragmentation&#xff09;机制 2.1 分片触发条件 2.2 分片支…

harmonyOS NEXT开发与前端开发深度对比分析

文章目录 1. 技术体系概览1.1 技术栈对比1.2 生态对比 2. 开发范式比较2.1 鸿蒙开发范式2.2 前端开发范式 3. 框架特性对比3.1 鸿蒙 Next 框架特性3.2 前端框架特性 4. 性能优化对比4.1 鸿蒙性能优化4.2 前端性能优化 5. 开发工具对比5.1 鸿蒙开发工具5.2 前端开发工具 6. 学习…

OpenWebUI:一站式 AI 应用构建平台体验

&#x1f680; 大家好&#xff0c;今天给大家分享一个超棒的 AI 应用构建工具——OpenWebUI&#xff01;体验下来&#xff0c;只能说丝滑&#xff01;必须强烈推荐&#xff01; &#x1f525; 听说过阿里巴巴的 Qwen 吗&#xff1f;他们最新的 Qwen Chat 网站就是用 OpenWebUI…

多线程—进程与线程

1 进程 1.1 进程概念 进程&#xff1a;操作系统提供的一种抽象&#xff0c;当程序在运行时&#xff0c;好像计算机的所有硬件资源都在为其服务。换言之&#xff0c;进程就是程序的一次运行过程。进程是操作系统分配资源的基本单位。 注意&#xff1a;区分进程和程序&#xff0…

[原创](Modern C++)现代C++的关键性概念: 灵活多变的绑定: std::bind

[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 开发工具: Visual Studio、Delphi、XCode、C …

ssm框架之mybatis框架动态SQL

1 mybatis动态sql mybatis可以通过各种各样的标签在sql映射文件中实现如下功能 1、语句的动态拼接 2、前后缀格式处理 3、复杂参数处理 常用标签如下&#xff1a; 1.1 if标签 如下示例&#xff0c;当有一个入参为null或者空的时候的时候&#xff0c;不参与计算&#xff0c;…

Spring Boot 事务详解

Spring Boot 事务详解 引言 在现代应用程序中&#xff0c;事务管理是确保数据一致性和完整性的重要机制。Spring Boot 提供了强大的事务管理功能&#xff0c;使得开发者可以轻松地定义和管理事务。本文将详细介绍 Spring Boot 中的事务管理&#xff0c;包括事务传播行为、事务…

poetry使用

1.初始化 package name 填入口文件名 poetry init2.在本目录下虚拟 poetry config virtualenvs.in-project true 3.自动生成依赖文件和vent虚拟环境&#xff0c;管理本项目下载包 poetry add flask pandas numpy 4 4.下载依赖 poetry install 5.查看都安装了什么包 poe…

Git 新建本地分支并关联到远程仓库

文章目录 1、方法一2、方法二 1、方法一 A、新建本地分支&#xff1a; git checkout -b new-branch-nameB、push新分支到远程仓库&#xff1a; git push origin newBranchC、本地分支关联到远程&#xff08;选一个即可&#xff09;&#xff1a; git branch --set…