【C++】适配器模式 - - stack/queue/deque

news2024/11/24 12:46:49

目录

一、适配器模式

1.1迭代器模式

1.2适配器模式

二、stack

2.1stack 的介绍和使用

2.2stack的模拟实现

三、queue

3.1queue的介绍和使用

3.2queue的模拟实现

 四、deque(不满足先进先出,和队列无关)

4.1deque的原理介绍

4.2deque的特点(支持头删,支持随机访问)

4.3deque的底层结构(buffer+中控指针数组)

五、总结

答案一: 

答案二:

答案三:


一、适配器模式

1.1迭代器模式

其实我们在前面学习 string、vector 和 list 时就已经接触过设计模式了 – 迭代器就是一种设计模式;迭代器模式是封装后提供统一的接口 iterator,在不暴露底层实现细节的情况下,使得上层能够以相同的方式来访问不同的容器

1.2适配器模式

适配器模式则是:

用已有的东西封装转换出想要的东西


二、stack

2.1stack 的介绍和使用

 和我们以前学的容器不同,为了不破坏栈 LIFO 的特性,stack 不提供迭代器,所以 stack 不是迭代器模式,而是一种容器适配器

如图,stack 使用 dqueue 容器作为默认的适配容器(后面讲一个吕布和诸葛亮的参照),关于 dqueue 的内容,我们放在文章最后面讲。

stack的常用接口:

函数说明接口说明
stack()构造空的栈
empty()检测stack是否为空
size()返回stack中元素的个数
top()返回栈顶元素的引用
push()栈顶入栈
pop()栈顶出栈

2.2stack的模拟实现

在了解了适配器模式之后,我们就可以将适配器作为类的第二个模板参数,然后通过传递不同的适配容器来实现栈了:

 

如上,vector 和 list 都可以作为 stack 的适配容器,我们可以通过给定不同的第二个模板参数来使用不同的容器适配 stack;

但是出于随机抽取和缓存命中的考虑,vector 显然更适合作为 stack 的适配容器,那么我们可以还可以将 vector 设置为 stack 的默认适配容器,这样,我们以后定义栈对象时就不用显式指定 vector 了

stack.h 文件

#include <iostream>
#include <vector>
#include <list>

namespace lzy {
	template<class T, class Container = std::vector<T>>
	class stack {
	public:
		//构造和析构不用写,默认生成的构造和析构对于自定义类型会调用它们的构造和析构函数

		bool empty() const {
			return _Con.empty();
		}

		size_t size() const {
			return _Con.size();
		}

		T& top() {
			return _Con.back();  //数组尾部作为栈的栈顶
		}

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

		void push(const T& val) {
			_Con.push_back(val);  //在数组尾部插入数据
		}

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

	private:
		Container _Con;
	};
}

 测试代码:

void test_stack() {
	//stack<int, std::vector<int>> st1;
	//stack<int, std::list<int>> st2;

	//stack<int> st1;  //默认使用vector做适配容器
	//stack<int, std::list<int>> st2;  //使用其他容器做适配容器需要显式指定

	stack<int> st;
	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);
	st.push(5);

	cout << st.size() << endl;

	while (!st.empty()) {
		cout << st.top() << " ";
		st.pop();
	}
	cout << endl;
}

三、queue

3.1queue的介绍和使用

 和 stack 一样,queue 也是一种容器适配器,也不提供迭代器

可以看到,queue 也是使用 deque 作为默认适配容器,和之前一样,deque 我们放在最后面讲。

queue 常用接口的使用

函数声明接口说明
queue()构造空的队列
empty()检测队列是否为空
size()返回队列中有效元素的个数
front()返回队头元素的引用
back()返回队尾元素的引用
push()在队尾将元素val入队列
pop()将队头元素出队列

3.2queue的模拟实现

 

这里queue与stack不同的是,stack俩个均可,但是vector更好;但是队列这里头删用vector是效率很低的办法,所以队列只可以用list

queue.h

#pragma once

#include <iostream>
#include <vector>
#include <list>

namespace lzy {
	template<class T, class Container = std::list<T>>
	class queue {
	public:
		//构造和析构不用写,默认生成的构造和析构对于自定义类型会调用它们的构造和析构函数

		bool empty() const {
			return _Con.empty();
		}

		size_t size() const {
			return _Con.size();
		}

		T& front() {
			return _Con.front();  //第一个节点为队头
		}

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

		T& back() {
			return _Con.back();  //最后一个节点为队尾
		}

		const T& back() const {
			return _Con.back();  //最后一个节点为队尾
		}

		void push(const T& val) {
			_Con.push_back(val);  //在链表尾部插入节点
		}

		void pop() {
			_Con.pop_front();  //删除第一个节点
		}

	private:
		Container _Con;
	};
}

测试代码:

void test_queue() {
	queue<int> q; //默认使用list做适配容器
	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	q.push(5);

	cout << q.size() << endl;

	while (!q.empty()) {
		cout << q.front() << " ";
		q.pop();
	}
	cout << endl;
}

 


 四、deque(不满足先进先出,和队列无关)

4.1deque的原理介绍

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

4.2deque的特点(支持头删,支持随机访问)

我们的stack用vector是为了缓存命中,而且因为先进后出的特性用链表不合适

我们的queue用list是因为list的头删效率更高

但是deque横空出世,具有随机访问和头插头删效率不错的特点(只不过每一个特点都没有发挥到极致)

不过不可否认的是 deque 确实很适合作为 stack 和 list 的默认适配容器,毕竟它对于 stack 和 list 的通用的,这也是 STL 中选择 deque 作为 stack 和 queue 默认适配容器的原因。

deque 特别适合需要大量进行头插和尾部数据的插入删除、偶尔随机访问、偶尔中部插入删除的场景;不太适合需要大量进行随机访问与中部数据插入删除的场景,特别是排序

总结:他没有vector访问数据那么极致,也没有list插入数据那么牛逼,但是他俩个特点都有,作为俩个容器的适配器也是非常合适的!

4.3deque的底层结构(buffer+中控指针数组)

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

关于扩容:只有当中空指针数组满了,才会扩容

关于尾插:后面新开一个buffer

关于头插:前面新开一个buffer

关于随机访问:1.查询哪一个buffer2.查询在哪一个buffer的哪一个位置

五、总结

答案一: 

答案二:

答案三:

希望对大家有所帮助!

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

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

相关文章

基于matomo实现业务数据埋点采集上报

matomo是一款Google-analytics数据埋点采集上报的平替方案&#xff0c;可保护您的数据和客户的隐私&#xff1b;正如它官网的slogan: Google Analytics alternative that protects your data and your customers privacy; 该项目源码开源免费&#xff0c;支持私有化部署&#x…

零基础Linux_17(进程间通信)VSCode环境安装+进程间通信介绍+pipe管道mkfifo

目录 1. VSCode环境安装 1.1 使用VSCode 1.2 远程链接到Linux机器 1.3 VSCode调试 2. 进程间通讯介绍 2.1 进程间通讯的概念和意义 2.2 进程间通讯的策略和本质 3. 管道 3.1 管道介绍 3.2 匿名管道介绍 3.3 匿名管道示例代码 3.3.1 建立管道的pipe 3.3.2 匿名管道…

YOLOv5算法改进(10)— 如何去添加多层注意力机制(包括代码+添加步骤+网络结构图)

前言:Hello大家好,我是小哥谈。注意力机制是近年来深度学习领域内的研究热点,可以帮助模型更好地关注重要的特征,从而提高模型的性能。注意力机制可被应用于模型的不同层级,以便更好地捕捉图像中的细节和特征,这种模型在计算资源有限的情况下,可以实现更好的性能和效率。…

二十一、【文本工具组】

文章目录 横排文本工具字符选项卡段落文字 横排文本工具 需要注意的是一些不是免费的商业字体&#xff0c;一定不要拿去使用&#xff0c;否则后边很容易会受到法律索赔。 在制作海报等一些图形时&#xff0c;需要经常用到文本工具我们需要对文本进行变形&#xff0c;分段&…

Qt开发工程师成系统性长体系教程

QT跨平台开发工程师必备技术栈 基础原理-案例分析-项目实战&#xff0c;紧跟QT开发岗位技术需求. 一、Qt C 语言编程基础专栏 1.1 Qt C 语言编程基础 Visual Studio 2022安装C语言基础概述C指针与引用C类与对象(一)C类与对象(二)类的基它特性构造函数&析构函数&拷贝…

rhel8 nmcli学习

25.3.1 配置动态IP连接 25.3.1.1 配置IP 要使用 DHCP 分配网络时&#xff0c;可以使用动态IP配置添加网络配置文件&#xff0c;命令格式如下&#xff1a; # nmcli connection add type ethernet con-name connection-name ifname interface-name 例如创建名为net-test的动态…

虚拟机的发展史:从分时系统到容器化

一、前世 早期计算机的价格非常昂贵&#xff0c;一台计算机可能需要花费几十万甚至上百万美元。例如&#xff0c;ENIAC计算机&#xff0c;作为世界上第一台通用电子数字计算机&#xff0c;当时的造价约为48万美元。科学家或者工程师们需要计算机的能力&#xff0c;但是买不起整…

C. JoyboardCodeforces Round 902

C. Joyboard 样例1列表找规律&#xff1a; #include<iostream> #define int long long using namespace std; signed main() {int T;cin>>T;while(T--){int n,m,k;cin>>n>>m>>k;if(k1){cout<<1<<endl;}else if(k2){cout<<m…

vue2时间处理插件——dayjs

在vue时间处理上有很多的方法和实现&#xff0c;可以自己实现&#xff0c;但是效率不高&#xff0c;所以&#xff0c;在框架开发中我们一般不会手写&#xff0c;一般是使用集成的第三方插件来解决我们的问题&#xff0c;在vue3中大家一般都使用Moment.js来处理&#xff0c;所以…

Defects4j数据集安装及使用

一、Defects4j数据集安装 在Ubuntu系统上进行操作&#xff0c;具体的在&#xff1a;Defects4j数据集安装 二、Defects4j数据集的使用 1. 常用命令 Getting started ---------------- #### Setting up Defects4J 1. Clone Defects4J:- git clone https://github.com/rjust/d…

JOSEF约瑟 可调漏电继电器RT-LB230KS+Q-FL-100 导轨安装 配套零序互感器

一、产品用途及特点 RT-LB230KS漏电继电器&#xff08;以下简称继电器&#xff09;适用于交流电压为660V.至1140V电压系统中,频率为50Hz,电流15~4000A线路中做有无中性点漏电保护. 该继电器可与带分励脱扣器或失压脱扣器的断路器、交流接触器、磁力启动器等组成漏电保护装置&…

【ELK 使用指南】ELK + Filebeat 分布式日志管理平台部署

ELK和EFLK 一、前言1.1 日志分析的作用1.2 需要收集的日志1.3 完整日志系统的基本特征 二、ELK概述2.1 ELK简介2.2 为什么要用ELK?2.3 ELK的组件 三、ELK组件详解3.1 Logstash3.1.1 简介3.1.2 Logstash命令常用选项3.1.3 Logstash 的输入和输出流3.1.4 Logstash配置文件 3.2 E…

端到端的机器学习项目(Machine Learning 研习之六)

使用真实数据 当你在研习机器学习时&#xff0c;最好是使用真实世界中的数据&#xff0c;而不是采用人工数据。巧的是&#xff0c;数以千计的数据集可供选择&#xff0c;涵盖了各种领域。 流行的开放数据存储库&#xff1a; OpenML.orgKaggle.compaperswithcode.com UC Irvin…

阿里云服务器不能访问网络之安装mysql 提示连接超时

wget -i -c http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm 过了一段时间后提示 fail .......time out 链接超时 有可能你的服务器不能访问网络 因为宽带套餐 我购买的时候没有购 重新购买就行了

python爬取boss直聘数据(selenium+xpath)

文章目录 一、主要目标二、开发环境三、selenium安装和驱动下载四、主要思路五、代码展示和说明1、导入相关库2、启动浏览器3、搜索框定位创建csv文件招聘页面数据解析(XPATH)总代码效果展示 六、总结 一、主要目标 以boss直聘为目标网站&#xff0c;主要目的是爬取下图中的所…

【Candence报错】Discrepancy #i in TASK

问题描述 Candence LVS仿真提示网络不匹配 问题解决 检查原理图和Layout 注意&#xff1a;

穿越功耗墙,我们该从哪些方面提升“性能”?

目录 背景 功耗&#xff1a;CPU 的“人体极限” 并行优化&#xff0c;理解阿姆达尔定律 总结延伸 背景 我们知道 CPU 的性能时&#xff0c;我们提到了这样一个公式&#xff1a; 程序的 CPU 执行时间 指令数CPIClock Cycle Time 这么来看&#xff0c;如果要提升计算机的…

tracy 学习

https://github.com/wolfpld/tracy 适用于游戏和其他应用的实时、纳秒分辨率、远程控制、支持采样和帧率检测 Tracy 支持分析 CPU&#xff08;为 C、C 和 Lua 集成提供直接支持。同时&#xff0c;互联网上存在许多其他语言的第三方绑定&#xff0c;例如 Rust 、Zig、C # 、 OC…

【git】gitlab安装、备份

gitlab官网 官网&#xff1a;官网 中文官网&#xff1a;中文官网 作为一个英文不好的程序员&#xff0c;所以我都去中文网站去看了。下面也是带着大家去走走 安装gitlab 我不想写具体的安装方法&#xff0c;直接去逛网看下面是我的截图。步骤非常详细。 安装文档地址&…

Apacheb Shiro 1.2.4反序列化漏洞(CVE-2016-4437)

Apache Shiro 1.2.4反序列化漏洞&#xff08;CVE-2016-4437&#xff09; 1 在线漏洞解读: https://vulhub.org/#/environments/shiro/CVE-2016-4437/2 环境搭建 cd /home/kali/vulhub/shiro/CVE-2016-4437启动&#xff1a; sudo docker-compose up -d # 拉取下载并启动sud…