【C++】STL中stack和queue(适配器版)的模拟实现

前言:在此之前我们讲到了stack和queue还有deque的常见的使用方法,并且也在数据结构的时候用C语言去实现过栈和队列,今天我们将进一步的用C++去模拟实现stack和queue

💖 博主CSDN主页:卫卫卫的个人主页 💞
👉 专栏分类:高质量C++学习 👈
💯代码仓库:卫卫周大胖的学习日记💫
💪关注博主和博主一起学习!一起努力!
在这里插入图片描述


目录标题

  • 什么是适配器
  • Stack的模拟实现
    • Stack的基本结构
    • 常见函数的模拟实现
      • 入栈 - push(const T& x)
      • 出栈- pop()
      • 获取栈顶元素 - const T& top()
      • 栈中的元素个数 - size_t size()
      • 判断栈是否为空
    • 整体代码:
  • Queue的模拟实现
    • Queue的基本结构
    • 常见函数的模拟实现
      • 入队列- push(const T& x)
      • 出队列- pop()
      • 获取队头元素- const T& front()
      • 获取队尾元素- const T& back()
      • 获取队列元素个数 - size_t size()
      • 判断队列是否为空 - bool empty()
    • 整体代码


在讲stack和queue的模拟实现之前我们需要提到一个概念:适配器

什么是适配器

适配器是一种设计模式,也是一种编程工具,用于将一个类的接口转换成另一个类的接口。适配器模式允许不兼容的类之间能够协同工作。

在C++中,适配器是指通过改变容器的接口使其适用于不同的需求。适配器可以封装容器,以提供一种更简单、更有限的功能接口,或者可以通过改变容器的工作方式来满足特定的需求。

在STL(标准模板库)中,适配器包括以下几种:

  1. 迭代器适配器:用于改变迭代器的行为,如reverse_iterator适配器用于反向遍历一个容器。
  2. 容器适配器:用于改变容器的接口,如stack适配器用于实现堆栈功能。
  3. 函数适配器:用于改变函数的行为,如bind适配器用于绑定函数和参数,生成新的函数对象。

适配器模式是一种重要的设计模式,它提供了一种解决兼容性问题的方式,并且可以使代码更加灵活和可复用。在C++中,STL的适配器提供了方便的工具和容器,使开发者能够更好地处理不同的需求和场景。
在这里插入图片描述


Stack的模拟实现

Stack的基本结构

这里很多人就会说,我们在C语言实现栈的时候就是像下面这么写的呐,就和实现vector一样的方式去实现stack不就行了嘛?如果是要用这样的方式去实现,那么博主今天就不会提到适配器这个概念了。
在这里插入图片描述


代码思路: 既然我们使用适配器来帮助我们来实现stack,那就是说你这个容器适配器的功能要满足我们stack所需要的入栈、出栈、获取栈顶元素、判断是否为空等等。

namespace bit 
{//这里我们通过模板来灵活的选择底层的容器适配器,只需要适配器满足我们所需要的操作即可template<class T, class Container = deque<T>>//适配器class stack{private:Container _con;};

STL中对stack和queue默认选择deque作为其底层容器,主要是因为:

  1. stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。
  2. 在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的元素增长时,deque不仅效率高,而且内存使用率高。
  3. 当然了这里你也可以显示调用你想用的容器适配器例如vector和list也都是可以的。

常见函数的模拟实现

入栈 - push(const T& x)

代码思路: 这里我们知道栈的基本结构就是先入栈的会后出,后进栈的先出,我们只需要在容器的尾部进行尾插,即可完成入栈,但是我们需要注意的是我们是尾插,所以再出栈的时候就直接出容器尾部的元素即可。

void push(const T& x)//入栈
{_con.push_back(x);//调用适配器的push_back即可
}

出栈- pop()

代码思路:刚刚我们说过栈先进后出,并且我们是通过尾插来模仿入栈的操作,所以我们的最后一个元素就是最后尾插进来的元素,要想模拟出栈的操作就是对其进行尾删即可。

void pop()//出栈
{_con.pop_back();//删除容器尾部的元素
}

获取栈顶元素 - const T& top()

代码思路: 我们是通过尾插来表示入栈,栈顶的元素就是最后一个入栈的元素,因此我们直接返回容器尾部的元素就可以模拟出获取栈顶元素的操作

const T& top()//获取栈顶元素
{return _con.back();//调用适配器返回尾部的元素
}

栈中的元素个数 - size_t size()

代码思路: 这个就比较简单了,我们通过适配器返回当前元素个数即可

size_t size()//栈中的元素个数
{return _con.size();
}

判断栈是否为空

代码思路: 同理直接调用适配器的函数即可

bool empty()//判断栈是否为空
{return _con.empty();
}

整体代码:

namespace bit 
{//template<class T> //传统的写法//class stack//{//	private://	T* _a;//	int _top;//	int _capacity;//};template<class T, class Container = deque<T>>//适配器class stack{public:void push(const T& x)//入栈{_con.push_back(x);}void pop()//出栈{_con.pop_back();//删除容器尾部的元素就是出栈}size_t size()//栈中的元素个数{return _con.size();}const T& top()//获取栈顶元素{return _con.back();//返回队尾的元素}bool empty()//判断栈是否为空{return _con.empty();}private:Container _con;};
}

Queue的模拟实现

Queue的基本结构

代码思路:同理我们这里依然可以使用适配器帮助我们来模拟实现queue的基本结构,但是一定记住适配器里面的操作必须满足你所需要的操作

namespace bit
{template <class T, class Container = deque<T>>//调用适配器class queue{private:Container _con;};}

常见函数的模拟实现

入队列- push(const T& x)

代码思路: 这里我们依然提一下,队列是先进先出,后进的后出和栈是完全相反的,所以我们在入队列的时候尾插的时候要记住,出队列的时候就是该容器的第一个元素先出,最后一个元素就是最后进去的元素就是最后出

void push(const T& x)//入队列
{_con.push_back(x);//队列先进去的先出去,入队列就直接尾插
}

出队列- pop()

代码思路:刚刚我们提到了因为我们是尾插来模拟的入队列,所以出队列的时候就要通过删除第一个元素来模拟出队列,但是这里需要注意的是Vector中是没有pop_front()这个函数的,所以我们的适配器只能是List和deque

void pop()//出队列
{_con.pop_front();//出队列就依次头出即可,这里就不能用vector了,vector没有pop_front
}

获取队头元素- const T& front()

代码思路: 刚刚提到了容器的第一个元素就是队头元素,因此我们只需要获取第一个元素即可。

const T& front()//获取队头元素
{return _con.front();//通过适配器获取队头元素
}

获取队尾元素- const T& back()

代码思路:因为我们是尾插,所以队尾元素就是最后一个进去的元素,所以通过适配器获得队尾元素即可。

const T& back()//获取队尾元素
{return _con.back();//调用适配器获取队尾元素
}

获取队列元素个数 - size_t size()

代码思路:这个和前面的栈同理就不过多的讲解了

size_t size()
{return _con.size();
}

判断队列是否为空 - bool empty()

代码思路: 这个也是一样的直接调用适配器里面的函数即可

bool empty()
{return _con.empty();//同理调用适配器判断是否为空
}

整体代码

namespace bit
{template <class T, class Container = deque<T>>class queue{public:void push(const T& x)//入队列{_con.push_back(x);//队列先进去的先出去,入队列就直接尾插}void pop()//出队列{_con.pop_front();//出队列就依次头出即可,这里就不能用vector了,vector没有pop_front}size_t size(){return _con.size();}bool empty(){return _con.empty();}const T& front()//获取队头元素{return _con.front();}const T& back()//获取队尾元素{return _con.back();}private:Container _con;};
}

好啦,今天的内容就到这里啦,下期内容预告STL中的优先级队列的使用与模拟实现.


结语:今天的内容就到这里吧,谢谢各位的观看,如果有讲的不好的地方也请各位多多指出,作者每一条评论都会读的,谢谢各位。


🌏🗺️ 这里祝各位接下来的每一天好运连连 💞💞

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

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

相关文章

vue 之 vuex

目录 vuex 是什么 Vuex管理哪些状态呢&#xff1f; Vuex 页面刷新数据丢失怎么解决 1. 使用浏览器的本地存储 2. 使用 Vuex 持久化插件 3. 使用后端存储 注意事项 Vuex 为什么要分模块并且加命名空间 vuex 是什么 vuex 是专门为 vue 提供的全局状态管理系统&#xff0c…

【应用案例】如何解决无人驾驶车辆的动力转向问题

埃尔朗根-纽伦堡大学名称为高能赛车运动队(High-Octane Motorsports e.V.)的学生方程式车队都设计、构建和制造具有创新意义且独特的赛车。然后&#xff0c;他们将参加三种不同类别的大学生方程式比赛&#xff1b;该项赛事中的参赛队伍来自于世界各地。 电动、无人驾驶和燃油车…

Windows 11 24H2版首发体验!附详细更新升级安装教程

Windows 11 24H2 版首发体验&#xff01;这是微软2024年的大版本更新&#xff0c;新增超多新功能&#xff0c;以下会给你细细道来。这个版本目前小编亲测&#xff0c;使用非常流畅&#xff0c;没有什么明显问题。系统是已经集成了VB6/VC2005/VC2008/VC2010/VC2012/VC2013/VC201…

Dorkish:一款针对OSINT和网络侦查任务的Chrome扩展

关于Dorkish Dorkish是一款功能强大的Chrome扩展工具&#xff0c;该工具可以为广大研究人员在执行OSINT和网络侦查任务期间提供强大帮助。 一般来说&#xff0c;广大研究人员在执行网络侦查或进行OSINT信息收集任务过程中&#xff0c;通常会使用到Google Dorking和Shodan&…

2024年高考:计算机相关专业还值得选择吗?

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;日常聊聊 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 行业竞争现状 市场饱和与新兴技术的影响 如何保持竞争力 专业与个人的匹配度判断 专业核心课程与技术能力 个人兴趣与职业…

使用开源的zip.cpp和unzip.cpp实现压缩包的创建与解压(附源码)

目录 1、使用场景 2、压缩包的创建 3、压缩包的解压 4、CloseZipZ和CloseZipU两接口的区别 5、开源zip.cpp和unzip.cpp文件的下载 VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排…

【C语音 || 数据结构】二叉树--堆

文章目录 前言堆1.1 二叉树的概念1.2 满二叉树和完美二叉树1.3 堆的概念1.4 堆的性质1.4 堆的实现1.4.1堆的向上调整算法1.4.1堆的向下调整算法1.4.1堆的接口实现1.4.1.1堆的初始化1.4.1.2堆的销毁1.4.1.3堆的插入1.4.1.4堆的删除1.4.1.4堆的判空1.4.1.4 获取堆的数据个数 前言…

单体架构改造为微服务架构之痛点解析

1.微服务职责划分之痛 1.1 痛点描述 微服务的难点在于无法对一些特定职责进行清晰划分&#xff0c;比如某个特定职责应该归属于服务A还是服务B? 1.2 为服务划分原则的痛点 1.2.1 根据存放主要数据的服务所在进行划分 比如一个能根据商品ID找出商品信息的接口&#xff0c;把…

随手记:uniapp图片展示,剩余的堆叠

UI效果图&#xff1a; 实现思路&#xff1a; 循环图片数组&#xff0c;只展示几张宽度就为几张图片边距的宽度&#xff0c;剩下的图片直接堆叠展示 点击预览的时候传入当前的下标&#xff0c;如果是点击堆叠的话&#xff0c;下标从堆叠数量开始计算 <template><…

力扣每日一题(2024-06-13)2813. 子序列最大优雅度

基于官方题解&#xff0c;进行补充说明 给你一个长度为 n 的二维整数数组 items 和一个整数 k 。 items[i] [profiti, categoryi]&#xff0c;其中 profiti 和 categoryi 分别表示第 i 个项目的利润和类别。 现定义 items 的 子序列 的 优雅度 可以用 total_profit distinct_…

Flutter InteractiveViewer CustomPaint的使用总结

最近产品上有个图片编辑的需求&#xff0c;需要对编辑区域做放大和缩小&#xff0c; 以方便用户编辑图片。做起来远比博主当初预想的要难受。这期间遇到几个问题。一一做一下记录。 如果只是单纯的缩放&#xff0c;没有对缩放的内容进行改变和更新&#xff0c; 那么基本没啥问…

go语言,拼接字符串有哪些方式

目录 第一种方式&#xff1a; 使用加号"" 第二种方式&#xff1a; 使用fmt.Sprintf 第三种方式&#xff1a; 使用strings.Join 第四种方式&#xff1a; 使用strings.Builder 第五种方式&#xff1a; 使用bytes.Buffer go语言&#xff0c;拼接字符串的方式有…

pycharm基本使用(常用快捷键)

0.下载 pycharm官网下载 选择合适的版本&#xff0c;本文以2024.1为例 1.简单应用 常用快捷键 ctrlD 复制当前行 ctrlY 删除当前行 ctrlX 剪切当前行&#xff08;可用作删除&#xff0c;更顺手&#xff09; shift↑ 选中多行ctrlshiftF10 运行 shiftF9 调试ctrl/ 注释当前…

数据结构入门:探索数据结构第一步

0.引言 在我们的日常生活中&#xff0c;经常需要管理大量的数据&#xff0c;就譬如学校中有好几千个学生&#xff0c;中国有十三亿人口&#xff0c;对于那么多的数据进行查找、插入、排序等操作就会比较慢。人们为了解决这些问题&#xff0c;提高对数据的管理效率&#xff0c;…

HTML实现进度条/加载框模版

HTML加载 一、环形加载 1二、环形加载 2三、波形加载四、百分比环形五、进度条 一、环形加载 1 <div class"loader"></div>.loader {border: 16px solid #f3f3f3;border-radius: 50%;border-top: 16px solid #3498db;width: 120px;height: 120px;-webki…

JavaScript 在浏览器和 Node.js 里的运行流程

浏览器中的 JavaScript 运行流程 加载与解析 HTML&#xff1a;浏览器首先加载 HTML 文档&#xff0c;并开始解析构建 DOM 树。这一步骤包括下载并解析所有的 HTML 标记。 发现 JavaScript 资源&#xff1a;当浏览器遇到 <script> 标签时&#xff0c;解析过程会暂停并开始…

docker被封禁,怎么拉取镜像,打包所有镜像

因为docker被国内封禁了&#xff0c;所以我把电脑上之前的镜像全部打包出来了 你们也可以打包&#xff0c;我提供一个脚本&#xff0c;你运行即可 export_docker.sh #!/bin/bash# 导出目录 EXPORT_DIR"docker_images_backup" mkdir -p "$EXPORT_DIR"# 获…

Calibre版图验证工具调用_笔记

Siemens EDA Calibre版图验证工具调用 采用Cadence Virtuoso Layout Editor直接调用Siemens EDA Calibre工具需要进行文件设置&#xff0c; 在用户的根目录下&#xff0c;找到.cdsinit文件&#xff0c; 在文件的结尾处添加以下语句即可&#xff0c;其中&#xff0c;calibre.skl…

vue3 computed 返回计算内容

const ItemPercent computed(() > {return (item: any) > {const num item.polishTaskList.filter((row: any) > row.carryOutState 1).lengthreturn (num / item.polishTaskList.length) * 100}}) 我现在有一个列表 列表中有每一项 根据每一项的数据 计算 或显…

Java 中常校验时间格式的方法

前言&#xff1a; 在实际项目开发中&#xff0c;跟时间参数打交道是必不可少的&#xff0c;为了保证程序的安全性、健壮性&#xff0c;一般都会对参数进行校验&#xff0c;其他类型的参数校验很好实现&#xff0c;那你知道时间参数的是怎么校验的吗&#xff1f;估计部分朋友在…