deque的介绍

news2024/11/16 9:23:14

前言 

        为什么会存在deque呢?在c++标准库中deque是作为 stack和queue的底层容器就是deque,我们要是了解过list和vector就会知道这两种容器各有优劣,vector的优点是支持随机访问,进而可以支持排序和二分查找等算法,它的缺点是如果空间不够增容的话要付出一定的代价(性能的损失),头插头删和中间位置的插入删除需要挪动数据,因此比较慢,存在空间的浪费。

        vector的优点是不需要扩容,没有空间的浪费,任意位置的删除和插入都很快(时间复杂度是O(1)) ,但是它也有很大的缺点,就是不支持随机访问(这个缺陷导致很多的算法都不能采用它)。

        deque就是vector和list的代替方案,deque支持随机访问,而且任意位置的插入和删除都很快(时间复杂度为O(1)),空间的浪费也很少,所以可以用一个容器deque来替代vector和list,那么大家肯定很好奇它的底层是怎么实现的,那么让我们一起来看看吧!

目录

1.deque的接口介绍

2.deque实现随机访问和任意位置插入删除的原理

3.deque的缺陷


1.deque的接口介绍

        从上面的接口中我们发现deque不仅支持头尾的删除和插入(时间复杂度都是O(1))还支持operator[],这就可以很好的支持了随机访问。 

我们可以来使用一下:

#include<deque>
void test()
{
	deque<int> dq;
	dq.push_back(1);//尾插
	dq.push_back(2);
	dq.push_back(3);
	dq.push_back(4); 
	dq.push_back(5);
	dq.push_back(6);
	dq.push_back(7);
	for (int i = 0; i < dq.size(); ++i)
	{
		cout << dq[i]<<" ";
	}
	cout << endl;
	//尾删
	dq.pop_back();
	dq.pop_back();
	dq.pop_back();
	dq.pop_back();
	//头插
	dq.push_front(10);
	dq.push_front(20);
	dq.push_front(30);
	dq.push_front(40);
	for (auto& e : dq)
		cout << e << " ";//支持范围for就支持迭代器
	cout << endl;
	//头删
	dq.pop_front();
	dq.pop_front();
}
int main()
{
	test();
	return 0;
}

2.deque实现随机访问和任意位置插入删除的原理

         为什么deque可以成为vector和list的替代方案呢?因为deque在一定程度上弥补了list不支持随机访问的缺点,也弥补了vector头插头删效率低和增容代价大的缺点,那么deque是通过怎么样来实现的那呢?

        其实deque是一种折中的实现方式,它是通过一段一段的连续空间buf来存放数据的,这些buf则通map的中控映射来联系到一起,它是一种折中的实现方式。如图:

        map实际上一个指针数组用来存放这个一段段空间的地址,如果map中存满了,开一段更大的map然后将map中存放的数组拷到新的空间中就好了。

         那么deque是如何实现头插头删的呢,这一段一段的buf是从map的中间开始的,如果头插就在重新开一段buf空间,将数据插入buf中,再将新的buf的地址存到map的前面就可以了,如图:

        deque随机访问与它的迭代器实现有关,如图:         

         如果想要实现遍历的话,首先它的迭代器cur从first开始,判断cur是否等于last,如果不等于last,cur就一直++向后走,当cur等于last,node++,找到下一个buf,让first指向buf的开始,last指向buf的结束,cur从buf的开始向后走,直到走完所有的buf,如果是随机访问的话,就要进行计算来找到数据在哪个buf中。

        deque地层上是假想的连续空间,实际上是分段连续的,为了维护他整体连续和随机访问,才有了这么复杂的结构。

3.deque的缺陷

        deque看似很完美,但是实际上是有很大的缺陷的,它的迭代器实现的很复杂,而且在遍历的时候要频繁检查是否移动到某段小空间的边界,导致效率下降,随机访问的效率也不够高。而在序列式场景下,可能需要经常遍历,因此在实际中,需要线性结构时会优先考虑vector和list。

排序的效率测试,数据越多效率会越低,例如:

#include<vector>
#include<deque>
#include<iostream>
#include<time.h>
#include<algorithm>
using namespace std;
int main()
{
	int i = 0;
	srand((unsigned int)time(NULL));//给随机数种子
	vector<int> v1;
	deque<int> d1;
	while (i < 1000000)//分别给vector和deque相同的十万个随机数
	{
		int k = rand();
		v1.push_back(k);
		d1.push_back(k);
		i++;
	}
	//对vector和deque采用相同的算法进行排序,并记录时间
	int v1begin = clock();
	sort(v1.begin(),v1.end());
	int v1end = clock();

	int d1begin = clock();
	sort(d1.begin(), d1.end());
	int d1end = clock();

	cout << "vector的排序时间:" << v1end - v1begin << endl;
	cout << "deque的排序时间:" << d1end - d1begin << endl;

	return 0;
}

        那么为什么会选择deque作为stack和queue的底层默认容器呢?

        因为stack和 queue不需要遍历(它们是没有迭代器的),只需要在固定的一端或者两端操作即可,stack中元素增长时,deque比vector效率高(扩容时不需要搬运大量数据),queue中的元素增长时,deque不仅效率高,而且内存使用率高(与vector相比)。它们结合了deque的优点避开了deque的缺点。

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

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

相关文章

鼠标事件 获取鼠标坐标及点击事件

运行效果&#xff1a; 头文件 #ifndef MOUSEEVENT_H #define MOUSEEVENT_H #include #include #include #include class MouseEvent : public QMainWindow { Q_OBJECT public: MouseEvent(QWidget *parent 0); ~MouseEvent(); protected: void mousePressEvent(QMouse…

Linux:一键搭建ftp服务(vsftpd)

《TRO-23614-VSFTPD》 如果csdn收费 可以和我si liao 我会免费发给你 我发的这个是一个tar归档包&#xff0c;脚本就在其中 Linux&#xff1a;《tar》归档命令_鲍海超-GNUBHCkalitarro的博客-CSDN博客 tar xfz tarro_vsftpd.tar.gz -C /root/ # tar xfz tar包路径 -…

SpringBoot第27讲:SpringBoot集成MySQL - MyBatis 多个数据源

SpringBoot第27讲&#xff1a;SpringBoot集成MySQL - MyBatis 多个数据源 本文是SpringBoot第27讲&#xff0c;在某些场景下&#xff0c;Springboot需要使用多个数据源&#xff0c;以及某些场景会需要多个数据源的动态切换。本文主要介绍上述场景及 SpringBootMyBatis实现多个数…

【期末满分作业】C语言程序设计 实训1——奖学金评定系统的设计与实现(附带实验报告、源码以及解释)

大家好&#xff0c;各位努力奋斗的大学生小伙伴们&#xff01;今天&#xff0c;我将带你们领略一项令人惊叹的程序设计奇迹——《奖学金评定系统》&#xff01;是不是感到激动呢&#xff1f;别急&#xff0c;让我为你们揭开这个能让你在C语言程序设计中拿满分的秘密武器&#x…

ASP.NET Core MVC 从入门到精通之Identity入门

随着技术的发展&#xff0c;ASP.NET Core MVC也推出了好长时间&#xff0c;经过不断的版本更新迭代&#xff0c;已经越来越完善&#xff0c;本系列文章主要讲解ASP.NET Core MVC开发B/S系统过程中所涉及到的相关内容&#xff0c;适用于初学者&#xff0c;在校毕业生&#xff0c…

pikache靶场通关——XSS漏洞

文章目录 前言环境第一关、反射型xss(get)Step.1、输入特殊字符测试Step.2、输入js语句Step.3、在URL中输入js语句 第二关、反射性xss(post)Step.1、输入获取cookie的js语句 第三关、存储型xssStep.1、输入获取cookie的js语句Step.2、查看页面源码Step.3、感受危害性 第四关、D…

1 君正IPC芯片方案介绍

专栏特色 1、所有源码严格遵守统一的编码规范。 2、手把手教学&#xff0c;让你从零开始&#xff0c;深入了解君正方案IPC库的方方面面。 3、纯C接口&#xff0c;接口封装严谨&#xff0c;接口功能丰富&#xff0c;应用层调用简单便捷。 4、近二十年行业经验和技术积累打造的高…

风电光伏iEEE33节点蒙特卡洛概率潮流计算

基于蒙特卡洛法的概率潮流 以IEEE33节点的电网为研究对象 建立了光伏和风电的概率出力模型 采用蒙特卡洛法进行随机抽样 之后基于抽样序列进行概率潮流计算 最后得到电网的电压概率出力曲线

使用数字钥匙技术的车辆有多安全?

首发微信公众号网络研究院&#xff0c;关注获取更多。 虽然有几种不同的方法来实现汽车使用的数字钥匙&#xff0c;但安全的数字钥匙标准应该利用近场通信 (NFC) 和超宽带 (UWB) 结合蓝牙低功耗 (BLE) 来访问车辆&#xff0c;开始引擎&#xff0c;固定车辆&#xff0c;或授权各…

云原生之使用Docker部署Dashy个人导航页

云原生之使用Docker部署Dashy个人导航页 一、Dashy介绍1.1 Dashy简介1.2 Dashy特点 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、部署前准备工作4.1下载Dashy源码包4.2 查看D…

vue基础-ref (!)

&#xff01;1、ref 引用 在父组件中直接去调 子组件中的方法&#xff0c;使用ref 很简单&#xff0c;比父子传值 简单很多 1、使用ref引用DOM元素 第一步&#xff1a;给标签里 写 ref“xxx” 第二步&#xff1a;就可以用this.$refs.xxx 来拿到这个元素 使用 ! 2、使用ref引…

Spring - Bean的6种作用域

1、Bean作用域问题2、作用域定义2.1、Bean的6种作用域singleton 单例模式prototype 原型作用域request 请求作用域session 会话作用域application 全局作用域&#xff08;了解&#xff09;websocket 单例作用域 vs 全局作用域 2.设置作用域 1、Bean作用域问题 通过一个案例来看…

[工业互联-10]:PLC入门简介

目录 前言 PLC的用途 PLC的特点 PLC的分类 1、按PLC的控制规模分类 2、按PLC的控制性能分类 3、按PLC的结构分类 PLC的技术指标 1、硬件指标 2、软件指标 3、主要性能指标介绍 1) 存储容量 2) 输入/输出&#xff08;I/O&#xff09;点数 3) 扫描速度 4) 指令的功…

【Redis】五种数据结构

在内存种种存储形式如下&#xff1a;

练习2:逻辑回归

练习2&#xff1a;逻辑回归 介绍 在本练习中&#xff0c;您将实现逻辑回归并将其应用于两个不同的数据集。还将通过将正则化加入训练算法&#xff0c;来提高算法的鲁棒性&#xff0c;并用更复杂的情形来测试模型算法。 在开始练习前&#xff0c;需要下载如下的文件进行数据上…

90后程序员回家卖羊粪,月销售额120万!

不得不说&#xff0c;程序员是一个勤奋而又善于思考的群体。他们不只是代码写得好&#xff0c;善于逻辑思维&#xff0c;即使有一天不做程序员&#xff0c;转行其他岗位了&#xff0c;也能在新的岗位上面玩出花样。 早在2013年的时候&#xff0c;就有一位新浪的PHP程序员转行卖…

单点登录:CAS使用springboot main方法启动cas-server

1.下载demo git clone https://gitee.com/pelin0963/cas-server.git2.使用eclipse导入maven项目。此次我是用的spring tool suite 4导入的。 导入时会用较长时间&#xff0c;10分钟吧。需要下载很多资源。 3.报错&#xff0c;提示缺少jar包 Missing artifact net.shibbolet…

【java】使用 BeanUtils.copyProperties 11个坑(注意事项)

文章目录 背景第1个坑&#xff1a; 类型不匹配第2个坑: BeanUtils.copyProperties是浅拷贝第3个坑&#xff1a;属性名称不一致第4个坑&#xff1a;Null 值覆盖第5个坑&#xff1a;注意引入的包第6个坑&#xff1a;Boolean类型数据is属性开头的坑第7个坑&#xff1a;查找不到字段…

C语言strlen函数的缺陷与实现,strcpy函数的缺陷与实现,strcat函数的缺陷与实现,strcmp的实现。

1.strlen 函数原型&#xff1a; size_t strlen( const char *string );size_t 是无符号整型&#xff0c;相当于unsigned intconst char *string 是目标字符串 函数作用&#xff1a; 计算字符串的长度。 函数的模拟实现&#xff1a; size_t _strlen(const char * str) {ass…

地址解析省市区详细地址

项目代码源地址在我的github&#xff1a;https://github.com/weitw/address-analyzer 一、项目介绍 1、解析规则 将一个用户输入的地址&#xff0c;解析成省、市、区、详细地址的形式。 如果用户输入的不是标准的地址&#xff0c;则需要推测标准地址。例如用户输入&#xff…