【C++】stack、queue的模拟实现及deque介绍

news2024/12/28 2:17:39

一、stack

1. 以vector作为底层容器

从栈的接口中可以看出,栈实际是一种特殊的vector,因此使用vector完全可以模拟实现stack。

由于stack的所有工作是底层容器完成的,而这种具有“修改某物接口,形成另一种风貌”的性质,称为配接器(适配器),所以stack往往不被归类为容器,而是被归类为容器配接器(容器适配器)。

template<class T>
class stack
{
private:
		std::vector<T> _c;
public:

	stack() {}
	void push(const T& x)
	{
		_c.push_back(x);
	}
	void pop()
	{
		_c.pop_back();
	}
	T& top()
	{
		return _c.back();
	}
	const T& top()const
	{
		return _c.back();
	}
	size_t size()const
	{
		return _c.size();
	}
	bool empty()const
	{
		return _c.empty();
	}
};

2. 以list作为底层容器

stack的接口push_back、pop_back,除vector外,list也都具备,因此,以list作为stack的底层容器,一样能够轻易实现stack。

template<class T>
class stack
{
private:
		std::list<T> _c;
public:
	//……
};

这样修改底层成员变量很麻烦,可以增加一个模板参数并给缺省值,来实现根据传入参数使用不同底层容器的stack

template<class T, class Con = std::vector<T>>
class stack
{
private:
		Con _c;
public:
	//……
};

这样就可以像如下代码使用stack:

stack<int,list<int>> st1;//以list作为底层容器
stack<int> st2//以vector作为底层容器

二、queue

因为queue的接口中存在头删和尾插,因此使用vector来封装效率太低,故可以借助list来模拟实现queue

template<class T, class Con = std::list<T>>
class queue
{
private:
	Con _c;
public:
	queue() {}
	void push(const T& x)
	{
		_c.push_back(x);
	}
	void pop()
	{
		_c.pop_front();
	}
	T& back()
	{
		return _c.back();
	}
	const T& back()const
	{
		return _c.back();
	}
	T& front()
	{
		return _c.front();
	}
	const T& front()const
	{
		return _c.front();
	}
	size_t size()const
	{
		return _c.size();
	}
	bool empty()const
	{
		return _c.empty();
	}
};

查看官方文档发现,stack是以deque作为底层容器的缺省,那么deque是一种什么样的数据结构呢?

在这里插入图片描述

在这里插入图片描述


三、deque

1. deque概述

vector是单向开口的连续线性空间,deque(双端队列)则是一种双向开口的连续线性空间。双向开口是指可以在头尾两端进行插入和删除操作,虽然vector可以在头尾操作,但是头部操作效率极低。

在这里插入图片描述

deque和vector、list的比较:

  1. 与vector相比,deque在头部插入删除是常数时间
  2. 与list相比,deque空间利用率比较高

deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组

在这里插入图片描述

图中的map并不是STL中的map,它其实是一个T**,也就是说它是一个指针,指向的东西是一个指针数组(这些指针又指向了一块连续空间)

2. deque迭代器介绍

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

在这里插入图片描述

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

在这里插入图片描述

由于最后一个缓冲区还有4个空间,push三次不会引起缓冲区的再配置。如果尾端再添加一个元素,则引发新缓冲区的配置,finish迭代器改变,此时使用了4个节点。

3. deque的缺陷

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

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

但是,deque有一个致命缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到 某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历。

因此在实际中,需要线性结构时,大多数情况下优先考虑vector和list,deque的应用并不多,而目前能看到的一个应用就是,STL用其作 为stack和queue的底层数据结构

4. 选择deque作为底层默认容器的原因

stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性结构,都可 以作为stack的底层容器,比如vector和list都可以

queue是先进先出的特殊线性数据结构,只要具有push_back和pop_front操作的线性结构,都可以作为queue的底层容器,比如list。

但是STL中对stack和queue默认选择deque作为其底层容器,主要是因为:

  1. stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。
  2. 在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的元素增长时,deque不仅效率高,而且相较于list内存使用率高。

从以上可以看出,deque是vector和list的折中。

STL标准库中对于stack和queue的模拟实现:只需要将默认容器改为deque

template<class T, class Con = std::deque<T>>
class stack
{
private:
		Con _c;
public:
	//……
};
template<class T, class Con = std::deque<T>>
class queue
{
private:
		Con _c;
public:
	//……
};

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

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

相关文章

Dubbo学习

文章目录1.概念1.1 Dubbo特性1.2 设计架构2.快速开始2.1需求假设2.2.工程架构2.3 创建模块2.3.1 gmall-interface—公共接口层2.3.2 gmall-user—用户模块2.3.3 gmall-order-web—订单模块2.3.4 测试结果2.3.5 使用Dubbo改造2.3.6 注解版3.监控中心4.整合SpringBoot5.Dubbo配置…

高性能网络设计专栏-网络编程

以下是在零声教育的听课记录。 如有侵权&#xff0c;请联系我删除。 链接&#xff1a;零声教育官网 一、网络io与select&#xff0c;poll。epoll 网络IO &#xff0c;会涉及到两个系统对象 一个是 用户空间 调用 IO 的进程或者线程&#xff0c;另一个是 内核空间的 内核系统&a…

K_A11_007 基于STM32等单片机驱动K型热电偶( MAX6675) 串口与OLED0.96双显示

[TOC](K_A11_007 基于STM32等单片机驱动K型热电偶( MAX6675) 串口与OLED0.96双显示) 一、资源说明 单片机型号测试条件模块名称代码功能STC89C52RC晶振11.0592MK型热电偶( MAX6675) 模块STC89C52RC驱动K型热电偶( MAX6675)模块串口与OLED0.96双显示STM32F103C8T6晶振8M/系统时…

后端架构学习

心理预期 1. 什么是后端服务的架构&#xff1f;怎么去理解后端架构这个词&#xff1f; 学习架构的目的&#xff1a;可以更高效的解决复杂的业务问题和技术问题。对架构设计的一知半解会导致&#xff0c;设计不足或者多度设计的现象。架构师思考问题的角度 按出发点划分 从系统…

Linux虚拟机忘记密码

Linux虚拟机忘记密码 使用虚拟机过程中&#xff0c;我们有时会忘记root的登录密码&#xff0c;我们需要进入救援模式去命令passwd更改新的密码。 编辑模式(e) 在首页&#xff0c;按住e,进入编辑模式&#xff0c;找到LANGzh_CN.UTF-8&#xff0c;在末尾加上 init/bin/sh 挂载…

学长教你学C-day10-C语言数组

“同学们&#xff0c;我们前面讲过了变量和数据类型&#xff0c;我们来复习一下&#xff0c;用C语言变量存储数据1~10&#xff0c;然后再输出。小明小红你们上黑板来写&#xff0c;其他人写纸上就可以。” 小明和小红走向讲台拿起粉笔写下&#xff1a; 小红&#xff1a; #incl…

VS操作笔记1:添加项目与查看定义

1 在解决方案中添加项目 右击解决方案 点击“添加”——“新建项目”—— 创建新项目的方法与创建第一个时一样 创建之后&#xff0c;项目结构如下&#xff1a; 现在是两个项目&#xff0c;第一个c_test项目名称字体明显加粗&#xff0c;说明这是主项目&#xff0c;编译的时…

【Go基础】切片

切片 1. 切片的定义 切片&#xff08;slice&#xff09;是Golang中独有的数据类型。 数组有特定的用处&#xff0c;但是有不足之处 &#xff1a;运行时长度不可变。切片是随处可变的&#xff0c;它构建在数组之上&#xff0c;并且提供更强大的能力和便捷。 切片&#xff08…

vite构建vue项目目录简介

文章目录1.项目目录介绍2.开发插件安装3.vue组件中的语法规范(SFC 语法规范)4.npm run dev命令执行过程1.项目目录介绍 public 下面的不会被编译 可以存放静态资源assets 下面可以存放可编译的静态资源components 下面用来存放我们的组件App.vue 是全局组件main ts 全局的ts文…

react基础Day01-React概述脚手架搭建JSX组件

React基础知识点 目标 能够说出React是什么能够说出React的特点能够掌握React的基本使用能够使用React脚手架 什么是React &#xff08;★★★&#xff09; React是一个用于构建用户界面的javaScript库&#xff0c;起源于facebook的内部项目&#xff0c;后续在13年开源了出…

Mysql入门技能树-时间日期函数(二)-练习篇

EXTRACT 关于 Extract 操作和其它日期时间函数的对应关系&#xff0c;下列说法正确的是&#xff1a; 1.extract(mirosecond from date) 相当于 ms(date) 2.extract(second from date) 相当于 second(date) 3.extract(minute from date) 相当于 minute(date) 4.extract(hour f…

IO流(二)

1.对象流-ObjectInputStream和ObjectOutputStream&#xff08;处理流包装流&#xff09;的基本原理 看一个需求&#xff1a; 1.将int num100这个int数据保存到文件中&#xff0c;注意不是100数字&#xff0c;而是int 100,并且&#xff0c;能够从文件中直接恢复int 100 2.将Dog …

Excel工具类实现——基于poi5.2.3

初衷仅是因为网上的Excel工具类不是太老旧的方法&#xff0c;就是不是很满足我想法&#xff0c;就想要自己搞一个&#xff0c;不过还不支持合并单元格等复杂的操作&#xff0c;后续看看能不能优化&#xff0c;有大神有更好的方法&#xff0c;可以公众号联系我&#xff0c;让我学…

基于jsp+mysql+Spring的SpringBoot美容院预约管理系统设计和实现

基于jspmysqlSpring的SpringBoot美容院预约管理系统设计和实现 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文…

编制万年历的历程

初入编程之道的学子大都试编过万年历。万年历有二种&#xff1a;一为只有西历的月历&#xff0c;另一为有农历对照的月历或日历。编写万年历程序可以练练手&#xff0c;加深对编程语言的理解。记得我初入此道是在1994年&#xff0c;我那时刚买了486电脑&#xff0c;也刚开始有视…

概率论基本概念

全概率公式 P(B)P(BA1)P(BA2)...P(BAn) P(B) P(B|A1)P(A1) P(B|A2)P(A2) ... P(B|An)P(An)P(BA1)P(BA2)...P(BAn) 事件A1&#xff0c;A2&#xff0c;…构成一个完备事件组且都有正概率 某一个事件概率 这个事件*其他完备事件划分联合概率之和 联合概率 联合概率指的…

线程安全问题(2)

锁的相关知识&#xff1a; 1)这就是类似于说我们ATM机上面有一把锁&#xff0c;同一时刻&#xff0c;如果说人们之间不相互认识&#xff0c;那么通过这把锁就进行限制了说就限制了说一次只能有一个人来进来取钱&#xff0c;我们通过这样的锁&#xff0c;就可以来进行避免上述这…

ESP8266 Arduino开发 搭建web服务器与客户端开发

一、wifi 相关配置 1.1 无线终端 wifi 模式 此模式中&#xff0c;esp8266 会连接到指定 wifi 进行工作。 #include <ESP8266WiFi.h> // 本程序使用ESP8266WiFi库const char* ssid "home"; // 连接WiFi名&#xff08;此处使用home为示例&…

位运算相关

1.与运算 &#xff08;点我&#xff09; 这个题的大概意思&#xff1a;给222个数nnn和xxx&#xff0c;其中满足n&(n1)&(n2)&(n3)...&mxn\&(n1)\&(n2)\&(n3)...\&mxn&(n1)&(n2)&(n3)...&mx,求最小的mmm&#xff0c;只要满足m&g…

【异常】java11提示: Cannot find any provider supporting RSA/ECB/PKCS1Padding的问题

一、背景 项目中需要对敏感字段进行加密&#xff0c;但是加密方法中涉及到比较复杂的加密算法&#xff0c;这些算法都需要一个Provider&#xff0c;主要是用于初始化算法的。 以下是遇到的具体问题 二、报错截图 java.security.NoSuchAlgorithmException: Cannot find any pr…