C++STL~~deque

news2024/9/22 23:35:42

文章目录

    • deque的概念
    • deque的使用
    • deque的练习
    • 总结

deque的概念

deque(双端队列):是一种序列容器、是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。
在这里插入图片描述
deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个
动态的二维数组,其底层结构如下图所示:
在这里插入图片描述
双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问
的假象,落在了deque的迭代器身上,因此deque的迭代器设计就比较复杂,如下图所示:
在这里插入图片描述
deque是如何借助其迭代器维护其假想连续的结构
在这里插入图片描述

deque的使用

#include <iostream>
#include <deque>

int main() {
    // 创建一个整数类型的双端队列
    std::deque<int> myDeque;

    // 在尾部添加元素
    myDeque.push_back(10);
    myDeque.push_back(20);

    // 在头部添加元素
    myDeque.push_front(5);

    // 访问和打印元素
    std::cout << "Elements in the deque: ";
    for (const auto& element : myDeque) {
        std::cout << element << " ";
    }
    std::cout << std::endl;

    // 删除尾部元素
    myDeque.pop_back();

    // 删除头部元素
    myDeque.pop_front();

    // 再次打印元素
    std::cout << "Elements after pop operations: ";
    for (const auto& element : myDeque) {
        std::cout << element << " ";
    }
    std::cout << std::endl;

    // 通过索引访问元素
    std::cout << "The first element is: " << myDeque[0] << std::endl;

    return 0;
}

双端队列的基本操作,包括在两端添加和删除元素、遍历以及随机访问。通过这个例子,可以更好地理解deque容器的特性和用法,为在实际编程中使用双端队列提供了参考。

deque的练习

STL标准库中对于stack和queue的模拟实现
stack

#include<deque>
namespace TU
{
	template<class T, class Con = deque<T>>
	class stack
	{
	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(); 
		}
	private:
		Con _c;
	};
}

代码实现了一个简单的栈(stack)容器模板类。它使用了 C++ 的模板技术,可以存储不同类型的元素,并可以指定底层容器的类型(默认为deque)。

queue

#include<deque>
namespace TU
{
	template<class T, class Con = deque<T>>
	class queue
	{
	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(); 
		}
	private:
		Con _c;
	};
}

代码定义了一个名为queue的类模板,实现了一个简单的队列数据结构。它使用了 C++ 的模板技术,可以存储不同类型的元素,并可以指定底层容器的类型(默认为deque)。这个队列支持基本的队列操作,如入队、出队、获取队首和队尾元素、查询队列大小和判断队列是否为空。

总结

deque的特点
1.两端高效操作

  • deque的主要优势在于可以在其前端和后端快速地插入和删除元素,时间复杂度均为常量级别。这使得它非常适合那些需要在队列两端频繁进行操作的场景,比如实现栈(在一端进行插入和删除)和队列(在两端分别进行插入和删除)的数据结构。

2.动态大小

  • 与其他标准容器一样,deque可以根据需要自动调整其大小以容纳更多或更少的元素。它可以在运行时动态地增长或收缩,无需预先确定其最大容量。

3.随机访问

  • deque支持随机访问元素,就像数组一样。你可以使用下标运算符[]或迭代器在常量时间内访问任意位置的元素。这使得在需要随机访问元素的算法中,deque也能发挥作用。

4.内存布局

  • deque的内部实现通常由多个固定大小的缓冲区组成。这些缓冲区在逻辑上形成一个连续的序列,使得deque看起来像一个连续的容器。当需要在两端进行插入或删除操作时,deque可以根据情况在适当的缓冲区中进行操作,而不必像std::vector那样可能需要整体重新分配内存并移动元素。

deque的缺陷

  • 与vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩
    容时,也不需要搬移大量的元素,因此其效率是必vector高的。
  • 与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。
  • 但是,deque有一个致命缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑vector和list,deque的应用并不多,而目前能看到的一个应用就是,STL用其作为stack和queue的底层数据结构。

为什么选择deque作为stack和queue的底层默认容器
stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性
结构,都可以作为stack的底层容器,比如vector和list都可以;queue是先进先出的特殊线性数据
结构,只要具有push_back和pop_front操作的线性结构,都可以作为queue的底层容器,比如
list。但是STL中对stack和queue默认选择deque作为其底层容器,主要是因为:

  • stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进
    行操作。
  • 在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的
    元素增长时,deque不仅效率高,而且内存使用率高。
    结合了deque的优点,而完美的避开了其缺陷。

使用场景
1.实现栈和队列

  • 由于deque可以在两端高效地进行插入和删除操作,它非常适合用来实现栈和队列。例如,可以将元素从deque的一端推入表示入栈操作,从同一端弹出表示出栈操作;将元素从deque的一端推入表示入队操作,从另一端弹出表示出队操作。

2.存储历史记录

  • 可以用deque来存储用户操作的历史记录,允许用户在一定范围内回溯和前进。新的操作可以添加到deque的一端,而当用户回溯时,可以从另一端删除元素。

3.广度优先搜索算法

  • 在图的广度优先搜索算法中,deque可以用来存储待访问的节点。从deque的一端取出节点进行访问,并将其相邻的未访问节点添加到deque的另一端。这样可以保证先访问距离起点较近的节点。

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

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

相关文章

F12抓包12:Performance(性能)前端性能分析

课程大纲 使用场景: ① 前端界面加载性能测试。 ② 导出性能报告给前端开发。 复习&#xff1a;后端(接口)性能分析 ① 所有请求耗时时间轴&#xff1a;“网络”&#xff08;Network&#xff09; - 概览。 ② 单个请求耗时&#xff1a;“网络”&#xff08;Network&#xf…

FIB对芯片反向技术的贡献

目前由于国内在模拟集成电路设计领域的研究较为薄弱&#xff0c;芯片逆向分析便成为大多数模拟集成电路工程师基础实际模拟电路积累经验的有效途径&#xff0c;IC反向设计也成为推动国内集成电路设计进步的有效手段。在IC逆向分析与设计服务中&#xff0c;主要用FBI对IC线路进行…

计算机二级office操作技巧——Excel篇

文章目录 函数公式总结写在前面五大基本函数sum求和函数average求平均函数max求最大值函数min求最小值函数count求个数函数 rank排名函数if逻辑判断函数条件求个数函数countif单条件求个数函数countifs多条件求个数函数 条件求和函数sumifs多条件求和函数sumproduct乘积求和函数…

【学习笔记】线段树合并

前言 一般来说&#xff0c;线段树会有 O ( n ) O(n) O(n) 个节点。但是有的时候&#xff0c;整棵线段树就只进行了一次插入操作&#xff0c;这样只会有 O ( l o g n ) O(logn) O(logn) 个节点。 处理树上问题时&#xff0c;我们有时需要把儿子的信息合并到父亲节点。这个时候…

松理解数据库并发调度与可串行性

‍ 前言 在数据库系统中&#xff0c;多个事务的并发执行是不可避免的。然而&#xff0c;并发执行可能导致数据不一致的情况。为了解决这个问题&#xff0c;数据库管理系统&#xff08;DBMS&#xff09;使用调度策略来控制事务的执行顺序。本文将简洁地介绍可串行化调度这一概…

基于springboot旅游管理系统设计与实现

基于springboot旅游管理系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本旅游管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助使用…

[数据集][目标检测]智慧交通铁轨裂缝检测数据集VOC+YOLO格式4类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2709 标注数量(xml文件个数)&#xff1a;2709 标注数量(txt文件个数)&#xff1a;2709 标注…

通过对比理解C++智能指针

理论 概述 智能指针&#xff1a;把管理资源的责任交给了对象&#xff0c;这样我们在使用结束时不需要显式地释放资源&#xff0c;而是由析构函数自动完成这一工作 它是一个类模板&#xff0c;可以创建任意类型的指针对象 智能指针使用时&#xff0c;资源对象不能被重复释放&a…

【CSS|第1期】网页设计的演变:从表格布局到Grid布局

日期&#xff1a;2024年9月9日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉在这里插入代码片得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对…

调用系统的录音设备提示:line with format PCM_SIGNED 16000.0 Hz

javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 16000.0 Hz, 8 bit, mono, 1 bytes/frame, not supported. 打开 设置->隐私->麦克风->允许应用访问你的麦克风 与 16000Hz没关系 与 16000Hz没关系 与 16000Hz没关系

【iOS】dismiss多级的方法

前言 上次笔者总结过push和pop推入和推出界面的方法&#xff0c;这里对于dismiss多级的方法进行一个总结&#xff0c;推入推出方法可以看看笔者这篇博客&#xff1a;【iOS】UI学习——界面切换 dismiss推出多级的原理 当我们使用pop推入新的界面的时候&#xff0c;连续pop推…

复杂情感识别系统

复杂情感识别系统&#xff08;CERS&#xff09;是一种先进的技术平台&#xff0c;旨在通过分析情感的组合、相互关系及其动态变化来解读和识别复杂的情感状态。这种系统通常采用以下技术和方法&#xff1a; 机器学习与深度学习&#xff1a; 通过训练算法识别和解释大量情感数据…

从汇编语言到高级语言:人类计算机科学的伟大探索

从20世纪中叶第一台电子计算机的诞生&#xff0c;到如今的智能设备遍布全球&#xff0c;计算机科学的发展历程是一部充满着人类探索精神的伟大史诗。计算机语言作为人类与机器交流的桥梁&#xff0c;见证并推动了这一切。从最早的汇编语言到如今多样的高级语言&#xff0c;我们…

视频监控摄像头国标GB28181配置参数逐条解析

转载&#xff1a;视频监控摄像头国标GB28181配置参数逐条解析 现在的很多信息化项目&#xff0c;都会涉及到国标GB28181的视频监控产品&#xff0c;当我们配置这些国标平台&#xff0c;录像机&#xff0c;摄像头时&#xff0c;如果对相关参数的定义不清楚的话&#xff0c;会给我…

【Android 13源码分析】WindowContainer窗口层级-1-初识窗口层级树

在安卓源码的设计中&#xff0c;将将屏幕分为了37层&#xff0c;不同的窗口将在不同的层级中显示。 对这一块的概念以及相关源码做了详细分析&#xff0c;整理出以下几篇。 【Android 13源码分析】WindowContainer窗口层级-1-初识窗口层级树 【Android 13源码分析】WindowCon…

Redis基础数据结构之 quicklist 和 listpack 源码解读

目录标题 quicklist为什么要设计 quicklist&#xff1f;quicklist特点ziplist quicklist数据结构 listpacklistpack是什么&#xff1f;listpack数据结构ziplist干啥去了&#xff1f;为什么有listpack?什么是ziplist的连锁更新&#xff1f;listpack 如何避免连锁更新&#xff1…

从ANN到SNN的转换:实现、原理及两种归一化方法【MINIST、实战】

从ANN到SNN的转换&#xff1a;实现、原理及两种归一化方法 引言 随着神经形态计算的迅猛发展&#xff0c;脉冲神经网络&#xff08;Spiking Neural Networks, SNNs&#xff09;作为一种仿生神经计算模型&#xff0c;逐渐展现出其在低功耗和事件驱动计算领域的巨大潜力。不同于…

8.5LoG算子边缘检测

LoG的基本概念 LoG&#xff08;Laplacian of Gaussian&#xff09;算子是一种结合了高斯模糊和平滑处理的边缘检测方法。它通过先对图像应用高斯滤波器来去除噪声&#xff0c;然后再对结果应用拉普拉斯算子来检测边缘。LoG算子的主要优点是可以检测图像中的边缘和其他重要特征…

MPICH 源码编译 with ucx with cuda,应用示例

先基于 cuda 编译ucx 再基于 ucx 编译 mpich mkdir mpich mkdir ucx 1, 安装 ucx 预备环境&#xff1a; sudo apt-get install valgrind sudo apt-get install libibverbs-dev librdmacm-dev 下载ucx 源代码 git clone --recursive https://github.com/openucx/ucx.git cd…

堆排序,快速排序

目录 1.堆排序 2.快速排序 1.hoare版本 2.挖坑法 3.前后指针法 注意点 1.堆排序 void Swap(int* a, int* b) {int tmp *a;*a *b;*b tmp; } void adjustdown(int* a, int n, int parent) {int child parent * 2 1;while (child < n){if (child 1 < n &&am…