c++编程(19)——STL(5)容器适配器

欢迎来到博主的专栏——c++编程
博主ID:代码小豪


文章目录

    • 适配器adaptor
    • stack
    • queue
    • priority_queue
    • 传送门:

适配器adaptor

适配器看起来像一个容器,实际上adaptor并不属于容器的范畴,更像是一种专门用于某种容器的接口。

常用的适配器有stack、queue、priority_queue。

template <class T, class Container = deque<T> > class stack;
template <class T, class Container = deque<T> > class queue;
template <class T, class Container = vector<T>,class Compare = less<typename Container::value_type> > class priority_queue;

这些适配器的模板不仅仅能接收类型作为参数,也能接收容器的类型作为参数来实例化适配器。stack、queue、priority_queue允许用顺序容器来作为适配器的底层。顺序容器有vector、list、deque。因此这些适配器也被称为顺序容器适配器。

适配器的机制允许适配器选择一个容器作为底层,但是会提供特殊的接口来掩盖这些底层。比如以deque为底层的stack不允许头插元素,也不允许遍历整个容器。因此适配器更像是限定底层容器行为的容器

在下面,博主会模拟实现这三个适配器。但是相关的算法博主并不打算解释,因为这些内容博主已经在另一个专栏——c语言数据结构中讲过了。在文章的末尾,博主会附上链接。

stack

stack是一个先进后出(FILO)的数据结构,它只有一个头端的出口与入口,stack中插入元素、删除元素、访问元素都只能在头端进行操作。
在这里插入图片描述
由于stack的所有插入与删除的操作都在一端。因此,作为底层的容器必须支持在同一端进行数据的插入与删除操作,比如push_back,pop_back,push_front,pop_front等,因此可以作为stack适配器的底层容器有vectoor,deque,list。

而在这些容器当中,vector会有扩容造成额外的时间开销,而list的空间又较为臃肿,因此deque成为了stack最合适的底层容器,这是由于它拥有不错的头尾插入效率。

stack适配器的模拟实现如下:

template<class T,class container=deque<T>>
class stack
{
public:stack(const container& copy_con=container()):_con(copy_con) {;}void push(const T& val){_con.push_back(val);}void pop() { _con.pop_back(); }T& top() { return _con.back(); }const T& top()const { return _con.back(); }bool empty()const { return _con.empty(); }size_t size()const { return _con.size(); }
private:container _con;//底层容器
};

其实从这段代码就很好的体现了,适配器更像是限定底层容器行为的容器这一特性。因此从代码中可以发现,stack并没有设计属于自己的操作,也没有除底层容器以外的数据成员,stack适配器中一切对于stack操作的函数,其实是在对底层容器进行操作。比如像stack上push一个元素,实际上是在容器的尾端插入元素,取stack栈顶元素,实际上是在取容器的尾端元素。

从这里就可以看出,适配器其实是一个封装了底层容器的接口。拿一个例子举例,底层容器就像一个电灯泡,而适配器就是这个电灯泡的灯罩,如果我们用不同的灯罩来封装灯泡,其发光的效果会发生变化,但是底层的电灯泡是不会变的,只是灯罩变了,于是效果也就跟着变了。

从下面这段测试案例,也能佐证这个性质:

我们可以用性质不同的容器来作为stack的底层容器,但是由于stack限制了这些容器的操作,因此它们看起来没有两样

void testmystack()
{stack<int, vector<int>> stack1;//vector为底层stack1.push(1);stack1.push(2);stack1.push(3);stack1.push(4);stack1.push(5);while (!stack1.empty()){cout << stack1.top();stack1.pop();}cout << endl;stack<int, list<int>> stack2;//list为底层stack2.push(1);stack2.push(2);stack2.push(3);stack2.push(4);stack2.push(5);while (!stack2.empty()){cout << stack2.top();stack2.pop();}cout << endl;
}

后续不再放出测试案例

queue

queue是一种先进先出(FIFO)的数据结构,它有两个端,头端作为出口,尾端作为入口,queue只允许在尾端插入元素,在头端删除元素,以及只允许在头端访问元素
在这里插入图片描述

queue只允许在尾端插入数据,在头端删除数据,因此适配的底层容器必须拥有头尾删除的操作,比如list和deque,它们都有在双端删除、插入的函数。而vector则不行,因为vector没有push_front和pop_front。即没有双端插入、删除元素的能力。

template<class T, class container = deque<T>>
class queue
{
public:queue(const container& copy_con = container()):_con(copy_con) {;}void push(const T& val) { _con.push_back(val); }void pop() { _con.pop_front(); }const T& front()const { return _con.front(); }T& front() { return _con.front(); }bool empty() { return _con.empty(); }size_t size() { return _con.size(); }private:container _con;
};

priority_queue

priority_queue是一个很特殊的适配器,和stack与queue不同,priority拥有属于自己的算法,即堆算法,priority的底层容器虽然用的是vector和deque,但是实际上用的其实是heap,即堆。heap并不是STL中的容器,或者说它是一个只藏在算法中的容器。在一些STL的一些算法中可以看到heap的影子。

博主在这里并不像介绍堆算法,因此很早之间博主就已经实现过了,在这篇博客当中,博主更希望读者能够对适配器有一定的了解。

因此我们直接放上源代码吧。

template<class T,class container=deque<T>,class comp=less<T>>
class priority_queue

priority_queue存在一个目前尚未了解的STL组件,仿函数,博主将会不就得将来给大家带来仿函数的讲解,我们先在priority_queue当中一睹芳容。

这里仿函数传递的是STL中定义的仿函数less,其作用是生成一个大堆,如果想要priority_queue的底层算法用的是小堆,可以传入仿函数greater。

priority_queue的译名是优先级队列,在priority_queue当中插入的元素会按照某种规则排序(即大小堆的排序规则)。当我们pop掉一个元素时,priority_queue会将内部元素重新排列,以保持pop的元素总是队列中的最大值或最小值。(关于heap的数据结构,博主会在文末放上链接)

template<class T,class container=deque<T>,class comp=less<T>>
class priority_queue
{
public:priority_queue():_con(container()) {;}template<class inputiterator>priority_queue(inputiterator first, inputiterator last){while (first != last){_con.push_back(*first);first++;}create_heap();}void push(const T val){_con.push_back(val);adjustup(_con.size()-1);}void pop(){swap(_con[0], _con.back());_con.pop_back();adjustdown(0);}const T& top()const { return _con.front(); }T& top() { return _con.front(); }size_t size(){ return _con.size(); }bool empty() { return _con.empty(); }	
private:void create_heap()//向下调整建堆算法{for (int i = (_con.size() - 2) / 2; i >= 0; i--){adjustdown(i);}}void adjustdown(int parent)//向下调整算法{int child=parent*2+1;while (child < _con.size()){if (child + 1 < _con.size() && compare(_con[child], _con[child + 1])){child++;}if (compare(_con[parent], _con[child])){std::swap(_con[parent],_con[child]);	}elsebreak;parent=child;child = parent * 2 + 1;}}void adjustup(int child)//向上调整算法{int parent=(child-1)/2;while (parent != child){if (compare(_con[parent] , _con[child])){std::swap(_con[parent], _con[child]);}elsebreak;child = parent;parent = (child - 1) / 2;}}container _con;comp compare;};
}

传送门:

数据结构——栈
数据结构——队列
数据结构——堆

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

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

相关文章

智能不锈钢氮气柜温湿度氧含量控制介绍

智能不锈钢氮气柜通过集成精密的温湿度和氧含量控制系统&#xff0c;确保内部环境稳定在适宜存储敏感物料的条件。具体实现方式如下&#xff1a; 温度控制&#xff1a;智能氮气柜通常配备有精确的温度传感器以及加热或冷却系统。当内部温度偏离设定值时&#xff0c;系统会自动启…

0617_QT3

练习&#xff1a; #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//去掉头部this->setWindowFlag(Qt::FramelessWindowHint);//去掉空白部分this->setA…

Misc之图片隐写

前几天忙高数和c考试去了。。。Web毫无进展&#xff0c;学学这个放松一下 一、工具准备 这里目前使用的工具为kali上的工具和安装在电脑上的Winhex&#xff0c;010editor&#xff0c;Stegsolve 二、png图片隐写 这里我就直接用题目学习了&#xff0c;也是参考了csdn上大佬的…

一五三、MAC 安装MongoDB可视化工具连接

若没有安装brew包管理工具&#xff0c;在命令行输入安装命令 /bin/bash -c “$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)”上面步骤安装完成后&#xff0c;开始安装MongoDB&#xff0c;输入安装命令&#xff1a; brew tap mongodb/brewbrew u…

【前端】Nesj 学习笔记

1、前置知识 1.1 装饰器 装饰器的类型 declare type ClassDecorator <TFunction extends Function>(target: TFunction) > TFunction | void; declare type PropertyDecorator (target: Object, propertyKey: string | symbol) > void; declare type MethodDe…

GenICam标准(三)

系列文章目录 GenICam标准&#xff08;一&#xff09; GenICam标准&#xff08;二&#xff09; GenICam标准&#xff08;三&#xff09; GenICam标准&#xff08;四&#xff09; GenICam标准&#xff08;五&#xff09; GenICam标准&#xff08;六&#xff09; 文章目录 系列文…

黑马程序员2024最新SpringCloud微服务开发与实战 个人学习心得、踩坑、与bug记录Day3 全网最全

你好,我是Qiuner. 为帮助别人少走弯路和记录自己编程学习过程而写博客 这是我的 github https://github.com/Qiuner ⭐️ gitee https://gitee.com/Qiuner &#x1f339; 如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 &#x1f604; (^ ~ ^) 想看更多 那就点个关注吧 我会…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] K小姐和A先生的聚餐计划(200分) - 三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f…

SQL优化选对执行计划,查询速度提升1000倍 | OceanBase 应用实践

作者&#xff1a;爱可生数据库高级工程师任仲禹&#xff0c;擅长故障分析和性能优化。 本文通过一个案例&#xff0c;分享使用OceanBase时&#xff0c;SQL走错执行计划&#xff0c;而导致慢SQL的排查方法论。 案例背景 在使用OceanBase 3.2.3 版本的过程中&#xff0c;项目组反…

Java——IO流(字符流,字节流)

JavaIO的整体框架图 IO流从方向上来说&#xff0c;可以分为输入流和输出流&#xff1b; 从传输内容上来说&#xff0c;可以分为字符流和字节流 防止记混的口诀 所谓的IO&#xff0c;说白了就是数据在内存和硬盘之间的传输 输入流 %Reader %InputStream&#xff0c;从硬盘写…

C#——类和对象详情

类和对象 类 类是一种数据结构&#xff0c;它可以包含数据成员&#xff08;常量和字段&#xff09;、函数成员&#xff08;方法、属性、事件、索引器、运算符、实例构造函数、静态构造函数和析构函数&#xff09;以及嵌套类型。类类型支持继承&#xff0c;继承是一种机制&…

在 Selenium 中更改 User-Agent | 步骤与最佳实践

在 Selenium 中更改 User Agent 是许多网页抓取任务中的关键步骤。它有助于将自动化脚本伪装成常规浏览器&#xff0c;从而避免被网站检测到。本指南将带您了解如何在 Selenium 中更改 Google Chrome 的 User Agent&#xff0c;并提供最佳实践以确保您的网页抓取任务顺利进行。…

湿法消解石墨消解仪 应用化学分析领域石墨炉

石墨消解仪在化学实验中具有重要的作用。它是一种高级实验设备&#xff0c;广泛应用于化学分析领域&#xff0c;特别是在样品的前处理和测试前的样品制备过程中。 石墨消解仪采用高温高压技术&#xff0c;能够将固体样品中的有机和无机物质转化为可溶性的气体或液体形式。这种…

从0进入微服务需要了解的基础知识

文章目录 系统架构演化过程为什么要了解系统架构的演化过程技术发展认知技术选型与创新 演变过程单体架构分层-分布式集群微服务 分布式\集群\微服务 微服务中的核心要素-拆分原则项目拆分与复杂度微服务的拆分维度有哪些小结 微服务中的核心要素服务化进行拆分后一定是微服务&…

可通过小球进行旋转的十字光标(vtkResliceCursor)

前一段事件看到VTK的一个例子&#xff1a; 该案例是vtk.js写的&#xff0c;觉得很有意思&#xff0c;个人正好也要用到&#xff0c;于是萌生了用C修改VTK源码来实现该功能的想法。原本以为很简单&#xff0c;只需要修改一下vtkResliceCursor就可以了&#xff0c;加上小球&#…

自动生成列表,颜色随机 ,定时执行函数,10秒停止执行函数,按钮执行函数

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>颜色列表Color List</title><style>…

基于LangChain-Chatchat实现的RAG-本地知识库的问答应用[4]-高阶自定义模块

基于LangChain-Chatchat实现的RAG-本地知识库的问答应用[4]-高阶自定义模块 1.自定义分词器 在text_splitter文件夹下新建一个文件,文件名为您的分词器名字,比如my_splitter.py,然后在__init__.py中导入您的分词器,如下所示:from .my_splitter import MySplitter修改confi…

新课程《新课程》期刊是什么级别的刊物?

新课程《新课程》期刊是什么级别的刊物&#xff1f; 《新课程》是由山西出版传媒集团主管、山西三晋报刊传媒集团主办的教育类学术期刊&#xff0c;属于省级刊物。 该期刊的国内刊号为CN14-1324/G4&#xff0c;国际刊号为ISSN1673-2162。 其主要栏目包括教育教学类、课程篇、…

厂里教务之延迟任务精准发布文章

延迟任务精准发布文章 延迟任务概述 什么是延迟任务 定时任务&#xff1a;有固定周期的&#xff0c;有明确的触发时间 延迟队列&#xff1a;没有固定的开始时间&#xff0c;它常常是由一个事件触发的&#xff0c;而在这个事件触发之后的一段时间内触发另一个事件&#xff0c…

部署远程控制台访问服务Rttys,第三部分服务端(安装Rttys)

安装服务端Rttys之前可选先在客户端安装rtty。服务端采用GO语言实现&#xff0c;前端界面采用vue实现。 CMAKE的安装和客户端RTTY的安装请参考前两篇文章&#xff1a; Linux远程连接程序工具选型 Webssh与Rtty 部署远程控制台访问服务Rttys&#xff0c;第一部分客户端&#…