深入探讨【C++容器适配器】:现代编程中的【Stack与Queue】的实现

目录

一、Stack(栈)

1.1 Stack的介绍

1.2 Stack的使用

1.3 Stack的模拟实现

二、Queue(队列)

2.1 Queue的介绍

2.2 Queue的使用

2.3 Queue的模拟实现

三、容器适配器

3.1 什么是适配器

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

​编辑

总结


 

专栏:C++学习笔记 

上一卷:C++—list容器

在C++中,stackqueue是两种非常重要的数据结构,广泛应用于各种算法和系统中。本文将详细介绍这两种数据结构的基本概念、使用方法及其底层实现,并结合代码示例和运行结果进行详细讲解。

一、Stack(栈)

1.1 Stack的介绍

stack(栈)是一种容器适配器,专门用于后进先出(LIFO, Last In First Out)的操作环境中。栈的元素插入和删除操作只能在容器的一端进行,即栈顶。

栈的底层容器可以是任何标准的容器类模板或一些其他特定的容器类,这些容器类应支持以下操作:

  • empty(): 判空操作
  • back(): 获取尾部元素操作
  • push_back(): 尾部插入元素操作
  • pop_back(): 尾部删除元素操作

标准容器vectordequelist均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器,默认情况下使用deque

小李的理解:
栈就像是一叠盘子,你只能从顶部添加或移除盘子。这就意味着最后添加的盘子最先被移除(后进先出)。在C++中,栈的底层可以用多种容器实现,但一般默认用deque,因为它支持高效的尾部操作。

1.2 Stack的使用

stack的常用操作包括:

  • stack(): 构造空的栈
  • empty(): 检测stack是否为空
  • size(): 返回stack中元素的个数
  • top(): 返回栈顶元素的引用
  • push(val): 将元素val压入stack中
  • pop(): 将stack中尾部的元素弹出

示例代码

#include <stack>
#include <iostream>int main() {std::stack<int> s;s.push(1);s.push(2);s.push(3);std::cout << "Stack top: " << s.top() << std::endl; // 输出3s.pop();std::cout << "Stack top after pop: " << s.top() << std::endl; // 输出2return 0;
}

首先我们压入了三个元素1, 2, 3,栈顶元素是3。然后我们弹出了栈顶元素,栈顶变成了2。

小李的理解:
就像把三个盘子按顺序叠起来(1在最底下,3在最上面)。当我们移走最上面的盘子时,下面的盘子就成了新的顶部。

1.3 Stack的模拟实现

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

示例代码

#include <vector>
#include <iostream>namespace bite {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;};
}int main() {bite::stack<int> s;s.push(1);s.push(2);s.push(3);std::cout << "Custom stack top: " << s.top() << std::endl; // 输出3s.pop();std::cout << "Custom stack top after pop: " << s.top() << std::endl; // 输出2return 0;
}

这表明我们的自定义stack实现与标准库中的行为一致。

小李的理解:
我们自己实现了一个简单的栈,用vector来存储元素。每次添加元素时,将它们推到vector的尾部;每次移除元素时,从vector的尾部移除。这和我们平时用的栈行为完全一样。

二、Queue(队列)

2.1 Queue的介绍

queue(队列)是一种容器适配器,专门用于先进先出(FIFO, First In First Out)的操作环境中。队列的元素插入操作在容器的一端进行,即队尾,而提取操作在容器的另一端进行,即队头。

队列的底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。这些容器类应支持以下操作:

  • empty(): 检测队列是否为空
  • size(): 返回队列中有效元素的个数
  • front(): 返回队头元素的引用
  • back(): 返回队尾元素的引用
  • push_back(): 在队列尾部插入元素
  • pop_front(): 在队列头部删除元素

标准容器dequelist满足这些要求。默认情况下,如果没有为queue指定特定的底层容器,则使用deque

小李的理解:
队列就像排队买票,最早来的人最先买到票(先进先出)。在C++中,队列的底层可以用多种容器实现,但一般默认用deque,因为它支持高效的头尾操作。

2.2 Queue的使用

queue的常用操作包括:

  • queue(): 构造空的队列
  • empty(): 检测队列是否为空
  • size(): 返回队列中有效元素的个数
  • front(): 返回队头元素的引用
  • back(): 返回队尾元素的引用
  • push(val): 在队尾将元素val入队列
  • pop(): 将队头元素出队列

示例代码

#include <queue>
#include <iostream>int main() {std::queue<int> q;q.push(1);q.push(2);q.push(3);std::cout << "Queue front: " << q.front() << std::endl; // 输出1q.pop();std::cout << "Queue front after pop: " << q.front() << std::endl; // 输出2return 0;
}

首先我们压入了三个元素1, 2, 3,队头元素是1。然后我们弹出了队头元素,队头变成了2。

小李的理解:
就像排队买票,第一个人买了票离开,第二个人就成了最前面的人。

2.3 Queue的模拟实现

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

示例代码

#include <list>
#include <iostream>namespace bite {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;};
}int main() {bite::queue<int> q;q.push(1);q.push(2);q.push(3);std::cout << "Custom queue front: " << q.front() << std::endl; // 输出1q.pop();std::cout << "Custom queue front after pop: " << q.front() << std::endl; // 输出2return 0;
}

 

这表明我们的自定义queue实现与标准库中的行为一致。

小李的理解:
我们自己实现了一个简单的队列,用list来存储元素。每次添加元素时,将它们推到list的尾部;每次移除元素时,从list的头部移除。这和我们平时用的队列行为完全一样。

三、容器适配器

3.1 什么是适配器

适配器是一种设计模式,该模式是将一个类的接口转换成客户希望的另外一个接口。在STL中,stackqueue就是通过适配器模式将dequevector等容器类的接口转换成特定的LIFO或FIFO操作。

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

虽然stackqueue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为stackqueue只是对其他容器的接口进行了包装,STL中stackqueue默认使用deque。主要原因如下:

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

结合了deque的优点,而完美地避开了其缺陷,使其成为stackqueue的理想底层容器。

总结

C++中的stackqueue通过容器适配器实现,分别用于LIFO和FIFO操作。stackqueue的底层容器默认使用deque,但也可以根据需求选择其他标准容器。理解并灵活运用这些数据结构,对于高效编写算法和处理复杂数据具有重要意义。

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

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

相关文章

Apache Flink核心特性应用场景

Flink的定义 Apache Flink是一个分布式处理引擎&#xff0c;用于处理 无边界数据流&#xff0c; 有边界数据流上金秀贤有状态的计算。Flink能在所有常见的集群环境中运行&#xff0c;并能以内存速度和任意规模进行计算如下Flink官网的一张图 Flink 与Spark的区别 Flink 中处…

5.SpringBoot核心源码-启动类源码分析

目录 概述技巧spring boot 如何启动应用程序run方法里面核心逻辑 SpringApplicaiton.run(xxx.class,args)结束 概述 SpringBoot核心源码-启动类源码分析 技巧 如何给外部源码加注释&#xff0c;想要在源码中添加自己的注释&#xff0c;会弹出 file is read only&#xff0c;代…

【多媒体】Java实现MP4和MP3音视频播放器【JavaFX】【更多功能的播放器】【音视频播放】

在Java中播放视频可以使用多种方案&#xff0c;最常见的是通过Swing组件JFrame和JLabel来嵌入JMF(Java Media Framework)或Xuggler。不过&#xff0c;JMF已经不再被推荐使用&#xff0c;而Xuggler是基于DirectX的&#xff0c;不适用于跨平台。而且上述方案都需要使用第三方库。…

GD32MCU最小系统构成条件

大家是否有这个疑惑&#xff1a;大学课程学习51的时候&#xff0c;老师告诉我们51的最小系统构成&#xff1f;那么进入32位单片机时代&#xff0c;gd32最小系统构成又是怎么样的呢&#xff1f; 1.供电电路 需要确保供电的电压电流稳定&#xff0c;以东方红开发版为例&#xff…

WPF界面设计-更改按钮样式 自定义字体图标

一、下载图标文件 iconfont-阿里巴巴矢量图标库 二、xaml界面代码编辑 文件结构 &#xe653; 对应的图标代码 Fonts/#iconfont 对应文件位置 <Window.Resources><ControlTemplate TargetType"Button" x:Key"CloseButtonTemplate"…

浏览器输入URL后的过程

总体流程&#xff1a; 1. 用户输入URL并按下回车 当用户在浏览器的地址栏中输入一个 URL 并按下回车&#xff0c;浏览器开始解析用户输入并判断这是一个合法的 URL。 2. DNS 解析 缓存查找&#xff1a;浏览器首先查看本地 DNS 缓存中是否有对应的 IP&#xff0c;如果有则直接…

AI人工智能作词,为音乐注入未来之力

在当今的音乐世界中&#xff0c;创新的力量不断推动着边界的拓展&#xff0c;而人工智能作词正以其独特的魅力&#xff0c;成为引领音乐走向未来的强大动力。 “妙笔生词智能写歌词软件&#xff08;veve522&#xff09;”无疑是这股浪潮中的璀璨明星。它利用先进的人工智能技术…

【Golang】map的使用

map声明的方式 //声明var m map[string]string//在使用map之前&#xff0c;先make&#xff0c;make的作用就是给map分配空间m make(map[string]string)m["lover"] "Yzx"m["friend1"] "Zxw"m["friend2"] "Zzc"…

快速测试electron环境是否安装成功

快速测试electron环境是否安装成功 测试代码正确运行的效果运行错误的效果v22.4.1 版本无法使用v20.15.1版本无法使用v18.20.4 版本无法使用 终极解决办法 测试代码 1.npx create-electron-app my-electron-app 2.cd my-electron-app 3.npm start 正确运行的效果 环境没问题…

47、lvs之DR

1、DR模式&#xff1a; 1.1、lvs三种模式&#xff1a; nat 地址转换 DR 直接路由模式 tun 隧道模式 1.2、DR模式的特点&#xff1a; 调度器在整个lvs集群当中是最重要的&#xff0c;在nat模式下&#xff0c;即负载接收请求&#xff0c;同时根据负载均衡的算法转发流量&…

智能家居装修怎么布线?智能家居网络与开关插座布置

打造全屋智能家居。计划的智能家居方案以米家系列为主&#xff0c;智能家居联网方案以无线为主。装修前为了装备智能家居做了很多准备工作&#xff0c;本文深圳侨杰智能分享一个智能家居装修和布线方面的心得与实战知识。希望能对大家的装修有所帮助。 ​1.关于网络 如果房子比…

C语言中字符串(字符数组)中含有 0x00 (‘\0‘)引发的问题和解决办法

问题 在C语言中&#xff0c;字符串是以空字符&#xff08;null character&#xff0c;即\0或0x00&#xff09;结尾的字符数组。这种设计意味着字符串中的任何 0x00 字符都会被解释为字符串的结束。因此&#xff0c;如果字符串内部包含0x00字符&#xff0c;这实际上会将字符串分…

【每日一练】python类和对象现实举例详细讲解

""" 本节课程目的&#xff1a; 1.掌握类描述现实世界实物思想 2.掌握类和对象的关系 3.理解什么事面向对象 """ #比如设计一个闹钟&#xff0c;在这里就新建一个类 class Clock:idNone #闹钟的序列号&#xff0c;也就是类的属性priceNone #闹…

Web开发 —— 放大镜效果(HTML、CSS、JavaScript)

目录 一、需求描述 二、实现效果 三、完整代码 四、实现过程 1、HTML 页面结构 2、CSS 元素样式 3、JavaScript动态控制 &#xff08;1&#xff09;获取元素 &#xff08;2&#xff09;控制大图和遮罩层的显隐性 &#xff08;3&#xff09;遮罩层跟随鼠标移动 &…

golang 项目打包部署环境变量设置

最近将 golang 项目打包部署在不同环境&#xff0c;总结一下自己的心得体会&#xff0c;供大家参考。 1、首先要明确自己目标服务器的系统类型(例如 windows 或者Linux) &#xff0c;如果是Linux 还需要注意目标服务器的CPU架构(amd或者arm) 目标服务器的CPU架构可执行命令&…

Vue.js学习笔记(五)抽奖组件封装——转盘抽奖

基于VUE2转盘组件的开发 文章目录 基于VUE2转盘组件的开发前言一、开发步骤1.组件布局2.布局样式3.数据准备 二、最后效果总结 前言 因为之前的转盘功能是图片做的&#xff0c;每次活动更新都要重做UI和前端&#xff0c;为了解决这一问题进行动态配置转盘组件开发&#xff0c;…

如何更好地理解递归算法?Python实例详解

递归确实是一种较为抽象的数学逻辑&#xff0c;可以简单的理解为程序调用自身的算法。 维基百科对递归的解释是&#xff1a; 递归&#xff08;英语&#xff1a;Recursion&#xff09;&#xff0c;又译为递回&#xff0c;在数学与计算机科学中&#xff0c;是指在函数的定义中使…

pbootCMS 数据库sqlite转mysql数据库

前言 pbootCMS默认使用 sqlite数据库 &#xff0c;那么什么是sqlite数据库呢&#xff1f; SQLite&#xff0c;是一款轻型的数据库&#xff0c;是遵守ACID的关系型数据库管理系统&#xff0c;它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌…

【大模型LLM面试合集】大语言模型架构_MoE论文

1.MoE论文 参考文章&#xff1a; Mixture of Experts-IntroductionUnderstanding the Mixture-of-Experts Model in Deep Learning 论文相关&#xff1a; 论文名称&#xff1a;Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer论文地址&a…

Kafka(三)Producer第二篇

一&#xff0c;生产者架构 生产者客户端由两个线程协调运行&#xff0c;分别为主线程和Sender线程&#xff08;发送线程&#xff09;。 主线程&#xff1a;KafkaProducer创建消息&#xff0c;通过拦截器、序列化器和分区器之后缓存到消息收集器RecordAccumulator中&#xff1b;…