Cpp::STL—容器适配器Stack和Queue的讲解和模拟实现(15)

文章目录

  • 前言
  • 一、适配器模式
    • 概念
    • 分类
  • 二、Stack
    • 核心作用
    • 代码实现
  • 三、Queue
    • 核心作用
    • 代码实现
  • 四、deque双端队列
    • 貌似兼收并蓄?
    • 实则也难以兼得~
  • 总结


前言

  适配器也是STL六大组件之一,请跟我一起领悟它的智慧!
  正文开始!


一、适配器模式

概念

  适配器(配接器)是 STL 中的六大组件之一,扮演着轴承、转换器的角色,使得 STL 中组件的使用更为灵活,比如 栈和队列 就是属于适配器而非容器,以及神秘的反向迭代器也属于适配器

有点像这个
在这里插入图片描述

分类

  我们可以把适配器分为以下三种

 容器适配器 container adapters
 迭代器适配器 iterator adapters
 仿函数适配器 functor adapters

  容器适配器可修改底层指定容器,如由 vector 构成的栈、由 list 构成的队列;迭代器适配器可以实现其他容器的反向迭代器(后续介绍);最后的仿函数适配器就厉害了,几乎可以无限制的创造出各种可能的表达式

在这里插入图片描述

出自侯捷老师的《STL源码剖析》

二、Stack

核心作用

  栈Stack其实是老熟人了,只是这里以另一种视角再次审视它一下

Stack特点是元素特定容器的尾部(即是栈顶)被压入和弹出

在这里插入图片描述
我们可以看到Stack的核心接口有:

  1. empty:判空操作
  2. size:获取元素个数操作
  3. back:获取尾部元素操作
  4. push_back:尾部插入元素操作
  5. pop_back:尾部删除元素操作

并且我们再看第二个模板参数 Container 表示实现栈时用到的底层容器,这里为缺省参数,缺省结构为 双端队列 deque< T >

代码实现

template<class T, class Container = deque<T>>
	class stack
	{
	public:
		void push(const T& x)
		{
			_con.push_back(x);
		}

		void pop()
		{
			_con.pop_back();
		}

		const T& top()
		{
			return _con.back();
		}

		bool empty()
		{
			return _con.empty();
		}

		size_t size()
		{
			_con.size();
		}
	private:
		Container _con;
	};

只要底层容器有我需要的函数接口,那么我就可以为其适配出一个容器适配器

在这里插入图片描述

三、Queue

核心作用

也是老熟人

Queue的最大特点是元素从队尾入队列,从队头出队列

在这里插入图片描述
我们可以看到Queue的核心接口有:

  1. empty:检测队列是否为空
  2. size:返回队列中有效元素的个数
  3. front:返回队头元素的引用
  4. back:返回队尾元素的引用
  5. push_back:返回队尾元素的引用
  6. pop_front:在队列头部出队列

并且我们看到第二个模板参数也为 deque< T >

代码实现

	template<class T, class Container = deque<T>>
	class queue
	{
	public:
		void push(const T& x)
		{
			_con.push_back(x);
		}

		void pop()
		{
			_con.pop_front();
		}

		const T& back()
		{
			return _con.back();
		}

		const T& front()
		{
			return _con.front();
		}

		bool empty()
		{
			return _con.empty();
		}

		size_t size()
		{
			_con.size();
		}
	private:
		Container _con;
	};

在这里插入图片描述

栈和队列都属于特殊的数据结构,原则上是不支持遍历的,因为一旦进行遍历,其中的数据必然被弹出,因此两者都没有提供迭代器

四、deque双端队列

貌似兼收并蓄?

在这里插入图片描述
  我们一看,它好像可以下标访问,也可以进行头部的插入和删除,功能很全面

  我们先要明确,deque(双端队列):是一种双开可口得"连续"空间数据结构

双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度O(1),与vector比较,头插效率高,不需要搬移元素,在扩容时,也不需要搬运大量的数据;与list比较,空间利用率比较高,不需要存储额外的字段

在这里插入图片描述

实则也难以兼得~

马跟驴生下了骡子,有一定的意义,但并不是说骡子完全在继承马跟驴的优点的基础上,完全规避了两者的缺点

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

在这里插入图片描述
  双端队列底层是一段假象的连续空间,实际是**分段且连续(一个buffer连续,几个buffer分段)**的,为了维护其"整体连续"以及随机访问的假象,落在了deque的迭代器身上,因此deque的迭代器设计比较复杂
在这里插入图片描述
  那deque是如何借助其迭代器维护其假想连续的结构呢

在这里插入图片描述

实现下标随机访问的原理

  1. (下标 - 前预留位) / 单个数组长度 获取对应小数组位置
  2. (下标 - 前预留位) % 单个数组长度 获取其在小数组中的对应下标

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


总结

  感觉如何,是不是被STL的魅力所折服了呢!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何实现简单的 WinCC 项目分屏?

说明&#xff1a; 本文主要介绍了在不使用分屏器的情况下&#xff0c;通过 WinCC 项目中的设置&#xff0c;实现简单的分屏操作。两台显示器分别显示不同的 WinCC 画面&#xff0c;独自操作&#xff0c;互不影响。 试验环境 &#xff1a; 本文试验时所用硬件及软件环境…

案例分享—国外优秀UI设计作品赏析

国外UI界面设计之所以出色&#xff0c;首要原因在于其注重用户体验。设计师们深入洞察用户需求&#xff0c;通过细致的用户调研和数据分析&#xff0c;确保界面布局、色彩搭配及交互方式都能贴合用户习惯&#xff0c;从而提供流畅、直观的操作体验&#xff0c;增强用户满意度和…

【MySQL】数据库基础、库的操作、表的操作、数据类型

目录 1. 数据库基础1.1 MySQL是什么1.2 使用案例1.3 服务器&#xff0c;数据库&#xff0c;表关系 2. 库的操作2.1 字符集和校验规则2.1.1 查看系统默认字符集以及校验规则2.1.2 查看数据库的字符集和校验规则2.1.3 修改数据库的字符集和校验规则 2.2 库的操作2.2.1 创建数据库…

c++算法第4天

本篇文章包含三道算法题&#xff0c;难度由浅入深&#xff0c;适合新手练习哟 第一题 题目链接 牛牛的快递_牛客题霸_牛客网 题目解析 <1kg -------> 20元 大于1kg&#xff1a;超出部分每千克1元 加急 5元 代码原理 代码编写 #include …

QT 实现自定义水波进度条

1.界面实现效果 以下是具体的项目需要用到的效果展示。 2.简介 原理:随着进度的改变,在我们的绘制图像void paintEvent(QPaintEvent *) override;事件中绘制图形。 使用QPainter来绘制正弦波,通过定时器,不断的更新我们绘制的图形,动态改变正弦波的参数来创建动画效果…

【从零开始的LeetCode-算法】3099. 哈沙德数

如果一个整数能够被其各个数位上的数字之和整除&#xff0c;则称之为 哈沙德数&#xff08;Harshad number&#xff09;。给你一个整数 x 。如果 x 是 哈沙德数 &#xff0c;则返回 x 各个数位上的数字之和&#xff0c;否则&#xff0c;返回 -1 。 示例 1&#xff1a; 输入&am…

提高阅读效率:三种读书笔记方法的实践

你是否曾经感到&#xff0c;尽管阅读了大量书籍&#xff0c;却很少有几本能够留下持久的印象&#xff0c;甚至书中的人物也逐渐从记忆中消失。实际上&#xff0c;这种阅读方式可能并没有太大的价值。要想真正从阅读中获益&#xff0c;培养良好的阅读习惯至关重要&#xff0c;而…

IDEA下lombok安装及找不到get,set的问题的解决方法

在IDEA中使用Lombok,但是在编译时&#xff0c;提示找不到set()和get()方法&#xff0c;明明在javabean中使用了Data注解&#xff0c;但是编译器就是找不到。 Idea下安装Lombok(需要二步) 第一步&#xff1a; pom.xml中加入lombok依赖包 1 2 3 4 5 6 7 <!-- https://mvnre…

Linux的开发工具gcc Makefile gdb的学习

一&#xff1a;gcc/g 1. 1 背景知识 1. 预处理&#xff08;进行宏替换) 预处理 ( 进行宏替换 ) 预处理功能主要包括宏定义,文件包含,条件编译,去注释等。 预处理指令是以#号开头的代码行。 实例: gcc –E hello.c –o hello.i 选项“-E”,该选项的作用是让 gcc 在预处理结…

如何在算家云搭建PhotoMaker(图像生成)

一、PhotoMaker简介 PhotoMaker是一种高效、个性化的文本转图像生成方法&#xff0c;能通过堆叠 ID 嵌入自定义的逼真人类照片。相当于把一张人类照片的特征提取出来&#xff0c;然后生成你想要的不同风格照片&#xff0c;如写真等等。 主要特点&#xff1a; 在几秒钟内快速…

远控代码的重构-远控网络编程的设计上

套路化代码 但是我们这是一个MFC工程,我们需要考虑不是所有操作都需要到main函数里面实现,有些操作可以在main函数之前完成,有些可以在main函数返回以后完成,静态全局变量满足这个需求,我们需要添加一个自己的类 编辑器细节1 添加类和添加类向导的区别,一个是添加自己的类,一…

ESP8266 模块介绍—AT指令学习 笔记

零、简介 感谢百文网韦东山 老师对ESP8266模块的讲解 笔记在CSDN也有文章备份 大家可以在我的gitee仓库 中下载笔记源文件、ESP8266资料等 笔记源文件可以在Notion中导入 一、ESP8266-01S模块详细介绍 1. 名字的由来 ESP8266 是方形的主控芯片旁边的长方形是一个Flash-0…

000010 - Mapreduce框架原理

Mapreduce框架原理 1. InputFormat 数据输入1.1 切片与 MapTask 并行度决定机制1.2 Job 提交流程源码和切片源码详解1.2.1 Job 提交流程源码详解1.2.2 FileInputFormat 切片源码解析&#xff08;input.getSplits(job)&#xff09; 1.3 FileInputFormat 切片机制1.3.1 切片机制1…

基于Springboot个性化图书推荐系统的设计与实现

基于Springboot个性化图书推荐系统的设计与实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;idea 源码获取&#xff1a;…

整理—计算机网络

目录 网络OSI模型和TCP/IP模型 应用层有哪些协议 HTTP报文有哪些部分 HTTP常用的状态码 Http 502和 504 的区别 HTTP层请求的类型有哪些&#xff1f; GET和POST的使用场景&#xff0c;有哪些区别&#xff1f; HTTP的长连接 HTTP默认的端口是什么&#xff1f; HTTP1.1怎…

兴业周报|央行宣布“有力度的降息”他来了

耕天下4号楼1单元5-103室&#xff08;复式&#xff09; 稀有户型&#xff1a;标的物为二环内南北通透4居室复式&#xff0c;低密度花园洋房&#xff0c;小区中心位置&#xff0c;前后不临街。 黄金地段&#xff1a;耕天下东接天坛公园、西靠陶然亭公园、南临南护城河、北抵先…

基于微信小程序二手物品调剂系统设计与实现

文章目录 前言项目介绍技术介绍功能介绍核心代码数据库参考 系统效果图文章目录 前言 文章底部名片&#xff0c;获取项目的完整演示视频&#xff0c;免费解答技术疑问 项目介绍 二手物品调剂系统是一种在线平台&#xff0c;旨在促进用户之间的二手物品交易。该系统提供了一个…

优雅的入参校验,Valid常用校验

更好的阅读体验&#xff1a;优雅的入参校验&#xff0c;Valid常用校验 对于前端传递的参数&#xff0c;正常情况下后端是要进行一些必要的校验&#xff0c;最简单的做法是用 if 效果是可以&#xff0c;但不优雅。使用 Validator 代替 if&#xff0c;就会优雅很多 ps&#xff…

【从零开发Mybatis】引入MapperConfig.xml和Mapper映射配置

引言 学习MyBatis源码之前&#xff0c;了解它是如何通过JDBC查询数据库数据的基础知识是非常有用的。 上一篇我们编写了一个最简单的示例&#xff0c;通过JDBC查询数据库数据&#xff0c;从本文开始&#xff0c;我们将正式开始Mybatis框架的开发。 通过JDBC查询数据库数据存…

中国移动机器人将投入养老场景;华为与APUS共筑AI医疗多场景应用

AgeTech News 一周行业大事件 华为与APUS合作&#xff0c;共筑AI医疗多场景应用 中国移动展出人形机器人&#xff0c;预计投入养老等场景 作为科技与奥富能签约&#xff0c;共拓智能适老化改造领域 天与养老与香港科技园&#xff0c;共探智慧养老新模式 中山大学合作中国…