【C++】通过栈和队列学会使用适配器和优先队列学会仿函数的使用

🌇个人主页:平凡的小苏
📚学习格言:命运给你一个低的起点,是想看你精彩的翻盘,而不是让你自甘堕落,脚下的路虽然难走,但我还能走,比起向阳而生,我更想尝试逆风翻盘
🛸C++专栏C++内功修炼基地
> 家人们更新不易,你们的👍点赞👍和⭐关注⭐真的对我真重要,各位路 过的友友麻烦多多点赞关注。 欢迎你们的私信提问,感谢你们的转发! 关注我,关注我,关注我,你们将会看到更多的优质内容!!

在这里插入图片描述

一、栈和队列的介绍

栈:

  1. stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。

  2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。

  3. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下

操作:

empty:判空操作

back:获取尾部元素操作

push_back:尾部插入元素操作

pop_back:尾部删除元素操作

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

队列

  1. 队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。

  2. 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定成员函数来访问其元素。元素从队尾入队列,从队头出队列。

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

empty:检测队列是否为空

size:返回队列中有效元素的个数

front:返回队头元素的引用

back:返回队尾元素的引用

push_back:在队列尾部入队列

pop_front:在队列头部出队列

  1. 标准容器类deque和list满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque。

二、栈的模拟实现

#pragma once
#include <iostream>
#include <vector>
#include <deque>
#include <stack>namespace sqy
{template <class T, class Container = std::vector<T>>class stack{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}T& top(){return _con.back();}bool empty(){return size() == 0;}size_t size(){return _con.size();}private:Container _con;};
}

在这里插入图片描述

注意:我们在模板上面添加对应栈结构的适配容器来支持栈的添加、删除、获取元素的操作。

并且我们将它设置为缺省参数,我们传参时就可以不传适配器,它就会使用自己默认的适配容器

三、队列的模拟实现

#pragma once
#include <iostream>
#include <list>
#include <deque>
#include <queue> 
namespace sqy
{template <class T, class Container = std::list<T>>class queue{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_front();}T& front(){return _con.front();}bool empty(){return size() == 0;}size_t size(){return _con.size();}private:Container _con;};
}

四、栈和队列使用不同的默认适配器的区别

栈使用的适配器

在这里插入图片描述

队列使用的适配器
在这里插入图片描述

1.栈使用vector作为适配器可以减少一直开辟空间的消耗,提高效率

2.队列使用list而不使用vertor,是因为vector不适用区头删元素,这是由于队列的特性导致vertor不适用

3 . 为此,STL标准库为了让栈和队列使用统一的适配器,又产生了一个新的适配器,也就是双端队列,这个容器适合给栈和队列当作默认适配器。

五、deque的原理简单介绍

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

  • deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组,其底层结构如下图所示:

在这里插入图片描述

双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问的假象,落在了deque的迭代器身上,因此deque的迭代器设计就比较复杂,如下图所示:
在这里插入图片描述

那deque是如何借助其迭代器维护其假想连续的结构呢?

使用cur进行++遍历,cur不等于last就一直进行++操作,当等于last后,node指向下个buffer,map存的是指针数组的映射,那么first和last也指向下一个的buffer的开头和结尾,cur指向first的位置,,往复如此,到最后一个buffer的时候,cur等于end()那么就遍历结束了

deque的源码解引用和判断操作
在这里插入图片描述

5.1 deque的缺点

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

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

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

六、priority_queue的介绍

在这里插入图片描述

优先级队列的特点是优先级高的先出。

​ 优先级队列是一种容器适配器,不提供迭代器,它的底层是一个堆(默认是大堆),这个堆默认使用vector进行适配。

priority_queue<int> pq;//pq底层为大堆
priority_queue<int,vector<int>,greater<int>> pq;//pq底层为小堆

6.1 优先队列中使用仿函数

仿函数,又称函数对象,它是一个类,类中重载了函数调用符号();这个运算符重载的返回值根据需要去给。

template<class T>
class Less
{public:bool operator()(const T& x,const T& y){return x < y;}
};template<class T>
class Greater
{public:bool operator()(const T& x,const T& y){return x > y;}
};

6.2 模拟实现优先级队列

#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
namespace sqy
{template<class T>class Less{public:bool operator()(const T& x,const T& y){return x < y;}};template<class T>class Greater{public:bool operator()(const T& x,const T& y){return x > y;}};template<class T, class Container = std::vector<T>, class Compare = Less<T>>class priority_queue{private:void AdjustUp(int child){Compare con;int n = _con.size();int parent = (child - 1) / 2;while(child > 0){if(con(_con[parent],_con[child])){swap(_con[parent],_con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}void AdjustDown(int parent){Compare con;int n = _con.size();int child = 2 * parent + 1;while(child < n){if(child + 1 < n && con(_con[child],_con[child+1])){child++;}if(con(_con[parent], _con[child])){swap(_con[parent],_con[child]);parent = child;child = 2 * parent + 1;}else{break;}}}public:priority_queue(){}template<class InputIterator>priority_queue(InputIterator first, InputIterator last){while(first != last){_con.push_back(*first);++first;}for(int i = _con.size() - 2; i >= 0; i--){AdjustDown(i);}}void pop(){assert(_con.size() != 0);swap(_con[0],_con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}void push(const T& x){_con.push_back(x);AdjustUp(_con.size() - 1);}const T& top(){assert(_con.size() != 0);return _con[0];}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};

注意:博主使用的是自己实现的仿函数,仿函数和c语言中的函数指针类似,但是祖师爷觉得使用c语言中的函数指针来比较大小太过于麻烦,所以祖师爷使用了仿函数的思想进行比较大小,这样我们想要比较自定义类型时,只要自定义类型写了运算符重载小于号和大于号,那就适用于给优先级队列,否则就会报错

还有一种情况:优先级队列存的是某个类的地址,但是需要比较指针指向值的优先级。那这个时候就不能用中的less和greater控制建堆,需要自己写仿函数。(仿函数也可以加上模板特化)

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

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

相关文章

pytorch安装GPU版本 (Cuda12.1)教程: Windows、Mac和Linux系统下GPU版PyTorch(CUDA 12.1)快速安装

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

vscode设置java -Xmx最大堆内存

如果在vscode中直接运行java程序&#xff0c;想要改下每次运行的最大堆内存&#xff0c;按照如下修改 一、vscode安装java插件 当然前提是vscode在应用管理中已经安装了java语言的插件&#xff0c;Debugger for Java,如下图所示 二、CommandShiftP打开配置搜索框 三、搜索…

dpdpdp

这里写目录标题 139. 单词拆分322. 零钱兑换300. 最长递增子序列120. 三角形最小路径和64. 最小路径和63. 不同路径 II5. 最长回文子串&#xff08;回文dp&#xff09;⭐97. 交错字符串⭐&#xff08;抽象成路径问题&#xff09;221. 最大正方形⭐ 139. 单词拆分 class Soluti…

代码随想录day8 | KMP 28.实现strStr() 459.重复的子字符串

文章目录 一、实现strStr()二、重复的子字符串 一、实现strStr() 先学学KMP算法&#xff0c;代码随想录 28.实现strStr() class Solution { public:void getNext(int* next, const string& s) {int j -1;next[0] j;for(int i 1; i < s.size(); i) { // 注意i从1开始…

微信小程序的微信一键登录与验证码登录

验证码登录 <template><view class"wx-login"><view class"login-Box"><text class"title">欢迎登录</text><text class"subTitle">再就业男团系统</text><view class"login-Form…

【算法基础:搜索与图论】3.3 拓扑排序

文章目录 拓扑排序介绍如何构造拓扑排序&#xff08;⭐重要&#xff01;&#xff09; 例题&#xff1a;848. 有向图的拓扑序列BFS 写法构造拓扑排序 相关题目练习207. 课程表&#xff08;判断是否存在拓扑序列&#xff09;bfs 写法dfs 写法 210. 课程表 II&#xff08;找到一个…

算法竞赛入门【码蹄集新手村600题】(MT1020-1040)

算法竞赛入门【码蹄集新手村600题】(MT1020-1040&#xff09; 目录MT1021 %f格式符MT1022 小数、指数MT1023 进制乱炖MT1024 进制形式MT1025 八、十六进制MT1026 合并MT1027 整数逆序MT1028 四位数逆序MT1029 位数MT1030 最大公约数MT1031 最简分数MT1032 最小公倍数MT1033 多项…

Docker 续

Docker 续 一、Docker 网络1.1 Docker 网络实现原理1.2 Docker 的网络模式1.2.1 Docker 网络模式分类 1.3 如何创建各类网络模式1.4 host模式1.5 container模式1.6 none模式1.7 bridge模式1.8 自定义网络 二、资源控制2.1 Cgroup2.2 CPU 资源控制2.2.1 设置CPU使用率上限2.2.2 …

c# Outlook检索设定问题

基于c# 设定outlook约会予定&#xff0c;时间格式是YYYY-MM-DD HH:mm 的情报。 问题发生&#xff1a; 根据开始时间&#xff08;2023/01/01 7:00&#xff09;条件查询该时间是否存在outlook信息时&#xff0c;明明存在一条数据&#xff0c;就是查询不出来数据 c#代码 Strin…

Observability:Synthetic monitoring - 动手实践

在我之前的如下文章里&#xff1a; Observability&#xff1a;Synthetic monitoring - 合成监测入门&#xff08;一&#xff09;&#xff08;二&#xff09; Observability&#xff1a;Synthetic monitoring - 创建浏览器监测&#xff0c;配置单独的浏览器监测器及项目 我详…

数据预处理matlab

matlab数据的获取、预处理、统计、可视化、降维 数据的预处理 - MATLAB & Simulink - MathWorks 中国https://ww2.mathworks.cn/help/matlab/preprocessing-data.html 一、数据的获取 1.1 从Excel中获取 使用readtable() 例1&#xff1a; 使用spreadsheetImportOption…

Vue整体架构分解

Vue.js的整体架构可以分解为以下几个部分: 文章目录 1. 数据驱动2. 组件化3. 响应式系统4. 虚拟DOM5. 插件系统6. 单文件组件7. 模板编译总结 1. 数据驱动 Vue的一个核心特点是数据驱动。Vue会在初始化的时候给数据提供一个observe监听&#xff0c;当数据变化时&#xff0c;会…

uniapp 微信小程序 input详解 带小数点的input、可查看密码的输入框input

官网文档地址 1、template <!-- 本示例未包含完整css&#xff0c;获取外链css请参考上文&#xff0c;在hello uni-app项目中查看 --> <template><view><view class"uni-common-mt"><view class"uni-form-item uni-column"&g…

【C++】开源:跨平台轻量日志库easyloggingpp

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍跨平台轻量日志库easyloggingpp。 无专精则不能成&#xff0c;无涉猎则不能通。。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&am…

详细介绍Matlab中线性规划算法的使用

Matlab中提供了用于线性规划的优化工具箱&#xff0c;其中包含了多种算法&#xff0c;如单纯形法、内点法等。线性规划是一种优化问题&#xff0c;旨在找到一组变量的最佳值&#xff0c;以最大化或最小化线性目标函数&#xff0c;同时满足一组线性约束条件。 下面将详细介绍Ma…

【C++11】智能指针的定义 和 种类 及 使用

智能指针 定义 为什么需要智能指针 在C中&#xff0c;动态分配内存是一项常见的任务&#xff0c;但手动管理分配和释放内存可能会导致很多问题&#xff0c;如内存泄漏、悬垂指针以及多次释放同一块内存等。为了避免这些问题&#xff0c;引入了智能指针的概念&#xff0c;它们…

LiveGBS流媒体平台GB/T28181功能-海康NVR摄像机自带物联网卡摄像头注册GB/T28181国标平台看不到设备的时候如何抓包及排查

海康大华宇视华为等硬件NVR摄像机注册到LiveGBS国标平台看不到设备的时候如何抓包及排查 1、设备注册后查看不到1.1、是否是自带物联网卡的摄像头1.2、关闭萤石云1.3、防火墙排查1.4、端口排查1.5、IP地址排查1.6、设备TCP/IP配置排查1.7、设备多网卡排查1.8、设备接入配置参数…

Docker(四)

文章目录 1. docker其他命令补充2. docker-registry使用3. docker-hub的使用4. 企业级私有仓库harbor4.1 harbor安装4.2 harbor配置https4.3 harbor常见使用4.3.1 harbor新建项目仓库4.3.2 harbor创建用户4.3.3 harbor仓库管理4.3.4 harbor复制管理4.3.5 harbor删除镜像 5. doc…

K8S下如何搭建eureka集群

背景 传统应用上云&#xff0c;基于传统应用需要考虑上云的方案和改造成本&#xff0c;这也是传统应用上云过程中的难点&#xff0c;本篇介绍3台eureka搭建的方案。 方案一 此方案借助了K8S中Service的一些功能。 这种方案是传统方案的简单迁移版本&#xff0c;比较易于理解…

深度学习:tf.keras实现模型搭建、模型训练和预测

在sklearn中&#xff0c;模型都是现成的。tf.Keras是一个神经网络库,我们需要根据数据和标签值构建神经网络。神经网络可以发现特征与标签之间的复杂关系。神经网络是一个高度结构化的图&#xff0c;其中包含一个或多个隐藏层。每个隐藏层都包含一个或多个神经元。神经网络有多…