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,一经查实,立即删除!

相关文章

关于渗透测试

目录 1渗透测试的目的 2渗透测试的手段 3渗透测试发现的问题分类 1渗透测试的目的 检验目的系统的安全性 2渗透测试的手段 1智能工具探测 2人工测试 3分析 3渗透测试发现的问题分类 SQL注入-高风险 垂直越权-高风险 链接注入-高风险 源码泄露-中风险 短信验证码重复利用-中风…

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

智能不锈钢氮气柜通过集成精密的温湿度和氧含量控制系统&#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上大佬的…

C语言socket TCP/IP通讯Server/Client程序(Ubuntu Linux 24.04环境)

继上篇文章介绍了Ubuntu Linux 24.04 C语言TCP/IP socket编程基础知识&#xff0c;本文将用C语言在Ubuntu Linux 24.04环境下开发一对使用socket进行TCP/IP通讯的Server/Client程序&#xff0c;实现的功能是&#xff1a; 1. 当client连上server时&#xff0c;显示连接成功的信…

MYSQL 数字(Aggregate)函数

目录 1、AVG() 2、MAX() 3、MIN() 4、SUM() 5、COUNT() 6、LIMIT() 1、AVG() 解释&#xff1a;返回数值列(字段)的平均值。 语法格式&#xff1a;SELECT AVG(column_name) FROM table_name 中文注释&#xff1a;select AVG(数值列/字段) from 表名 ; 用法&#xff1…

一五三、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; (^ ~ ^) 想看更多 那就点个关注吧 我会…

Spark大数据处理技术(期末复习)

Spark大数据处理技术&#xff08;期末复习&#xff09; 1)var a:Double5;var b:Int7;那么print(a*b) 35.0 2) var a:Int5; var bif(a>6) 7 println(b) 不满足 &#xff08;&#xff09; 3)var a:Int16; var b:Int13; var cif(a>b) 5 else 7; println(c) 5 4. object …

查看 RK3568 Android SDK 版本的详细指南

目录 前提条件方法一&#xff1a;通过getprop命令查看系统属性方法二&#xff1a;通过build.prop文件查看版本信息方法三&#xff1a;查看源码中的配置文件方法四&#xff1a;通过编译输出查看版本信息附录&#xff1a;常见问题及解决方法1. adb 命令找不到设备2. getprop 或 c…

【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;能够将固体样品中的有机和无机物质转化为可溶性的气体或液体形式。这种…

Helm是个啥

对于Helm的理解&#xff0c;最快的方法是对比yum。 yum是Linux的应用程序包管理器&#xff0c;可以下载应用程序&#xff0c;有时候还可以配置操作系统让下载的引用程序在后台启动&#xff0c;例如docker等。 Helm就相当于把kubernetes集群&#xff0c;看作一个Linux系统&…

Vue3表单组件el-form校验规则rules属性

Vue3表单组件el-form校验规则rules属性 一、前言1.基本用法2.示例代码3.校验规则详解4.自定义校验函数示例 二、总结 一、前言 在使用 Element UI (现在称为 Element Plus) 的表单组件 el-form 时&#xff0c;rules 属性用于定义表单项的校验规则。这些规则可以帮助你确保用户…