<C++> STL_deque

news2024/11/16 21:00:05

<c++> STL_deque

1.deque的使用

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tp0r6ALo-1693144180150)(C:\Users\32784\AppData\Roaming\Typora\typora-user-images\image-20230827212550686.png)]

构造和析构

  • std::deque<T>:创建一个存储类型为 T 的元素的双端队列。
  • std::deque(const std::deque<T>& other):复制构造函数,用另一个双端队列初始化当前队列。
  • ~std::deque():析构函数,释放内存。

示例:

#include <iostream>
#include <deque>

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

    // 在队尾插入元素
    myDeque.push_back(10);
    myDeque.push_back(20);
    myDeque.push_back(30);

    // 复制构造一个新的双端队列
    std::deque<int> anotherDeque = myDeque;

    // 输出原始队列的内容
    std::cout << "Original deque content:";
    for (const int& value : myDeque) {
        std::cout << " " << value;
    }
    std::cout << std::endl;

    // 输出复制构造的队列的内容
    std::cout << "Copied deque content:";
    for (const int& value : anotherDeque) {
        std::cout << " " << value;
    }
    std::cout << std::endl;

    // 注意:析构函数会在作用域结束时自动调用,释放内存
    return 0;
}

容量相关

  • size():返回队列中元素的数量。
  • empty():检查队列是否为空。

示例:

#include <deque>
#include <iostream>

int main() {
    std::deque<int> myDeque = {10, 20, 30, 40};

    std::cout << myDeque.size() << std::endl; //4
    std::cout << myDeque.empty() << std::endl;//0

    return 0;
}
  • resize(new_size):调整队列的大小。
void resize(size_type count); 
void resize(size_type count, const value_type& value);
  • count:新的队列大小。
  • value:在增加队列大小时用于填充新元素的默认值。

功能:

  • 如果 count 小于当前队列的大小,resize 会移除尾部的元素,使队列的大小变为 count
  • 如果 count 大于当前队列的大小,resize 会在尾部插入足够数量的默认值为 value 的元素,使队列的大小变为 count

示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque = {10, 20, 30};

    // 调整队列大小为 5,填充默认值 0
    myDeque.resize(5);

    for (const int& value : myDeque) {
        std::cout << " " << value;   // 10 20 30 0 0
    }
    std::cout << std::endl;

    // 调整队列大小为 3
    myDeque.resize(3);

    for (const int& value : myDeque) {
        std::cout << " " << value;  // 10 20 30
    }
    std::cout << std::endl;

    return 0;
}

元素访问

  • at(index):函数返回指定索引处的元素,并在访问之前进行范围检查。如果索引超出了双端队列的有效范围,将引发 std::out_of_range 异常。
  • operator[](index):运算符返回指定索引处的元素,但不进行范围检查。如果索引超出了有效范围,行为将是未定义的。
  • front():返回第一个元素的引用。
  • back():返回最后一个元素的引用。

示例:

#include <deque>
#include <iostream>

int main() {
    // 创建一个存储字符串的双端队列
    std::deque<std::string> myDeque;

    // 在队尾插入元素
    myDeque.push_back("Alice");
    myDeque.push_back("Bob");
    myDeque.push_back("Charlie");

    // 使用 at(index) 进行范围安全的访问
    try {
        std::string value = myDeque.at(1);// 索引1处的元素是 "Bob"
        std::cout << value << std::endl;  //Bob
    } catch (const std::out_of_range &e) {
        std::cout << "Index is out of range." << std::endl;
    }

    // 使用 operator[](index) 进行不安全的访问
    std::string unsafeValue = myDeque[2];// 索引2处的元素是 "Charlie"
    std::cout << "不安全: " << unsafeValue << std::endl;

    // 使用 front() 访问第一个元素
    std::string firstElement = myDeque.front();
    std::cout << firstElement << std::endl;

    // 使用 back() 访问最后一个元素
    std::string lastElement = myDeque.back();   //Alice
    std::cout << lastElement << std::endl;      //Charlie

    return 0;
}

修改操作

  • push_back(value):在队尾插入一个元素。
  • push_front(value):在队首插入一个元素。
  • pop_back():移除队尾的元素。
  • pop_front():移除队首的元素。
  • insert(pos, value):在指定位置插入一个元素。
  • erase(pos):移除指定位置的元素。
  • clear():移除所有元素。

示例:

#include <deque>
#include <iostream>

int main() {
    std::deque<int> myDeque;
    // 在队尾插入元素
    myDeque.push_back(10);
    myDeque.push_back(20);

    // 在队首插入元素
    myDeque.push_front(5);

    // 输出队列内容
    for (const int &value: myDeque) {
        std::cout << value << " ";//5 10 20
    }
    std::cout << std::endl;

    // 移除队尾的元素
    myDeque.pop_back();

    // 移除队首的元素
    myDeque.pop_front();

    // 输出队列内容
    for (const int &value: myDeque) {
        std::cout << value << " ";//10
    }
    std::cout << std::endl;

    // 在指定位置插入元素
    std::deque<int>::iterator it = myDeque.insert(myDeque.begin() + 1, 15);

    // 输出队列内容
    for (const int &value: myDeque) {
        std::cout << value << " ";//10 15
    }
    std::cout << std::endl;

    // 移除指定位置的元素
    myDeque.erase(it);

    // 输出队列内容
    for (const int &value: myDeque) {
        std::cout << value << " ";//10
    }
    std::cout << std::endl;

    // 清空队列
    myDeque.clear();

    if (myDeque.empty()) {
        std::cout << "Deque is empty.";
    } else {
        std::cout << "Deque is not empty.";
    }
    std::cout << std::endl;

    return 0;
}

迭代器

  • begin()end():返回指向第一个元素和尾后元素的迭代器。

示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque = {10, 20, 30, 40};

    for (std::deque<int>::iterator it = myDeque.begin(); it != myDeque.end(); ++it) {
        std::cout << " " << *it;  //10 20 30 40
    }
    std::cout << std::endl;

    return 0;
}
  • rbegin()rend():返回指向最后一个元素和首元素前一个位置的逆向迭代器。

示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque = {10, 20, 30, 40};

    for (std::deque<int>::reverse_iterator rit = myDeque.rbegin(); rit != myDeque.rend(); ++rit) {
        std::cout << " " << *rit;   //40 30 20 10
    }
    std::cout << std::endl;

    return 0;
}

2.deque的原理介绍

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

3.deque的优缺点

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

4.为什么选择deque作为stack和queue的底层默认容器

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不仅效率高,而且内存使用率高。

结合了deque的优点,而完美的避开了其缺陷。

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

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

相关文章

字节码操作的手术刀-Javassist

Javassist 前面文章介绍的 ASM 入门门槛还是挺高的&#xff0c;需要跟底层的字节码指令打交道&#xff0c;优点是小巧、性能好。Javassist 是一个性能比 ASM 稍差但是使用起来简单很多的字节码操作库&#xff0c;不需要了解字节码指令&#xff0c;由东京工业大学的数学和计算机…

求解整数规划问题的割平面法和分支定界法

文章目录 整数规划割平面法分支定界法代码实现 整数规划 整数规划问题是优化变量必须取整数值的线性或非线性规划问题&#xff0c;不过&#xff0c;在大多数情况下&#xff0c;整数规划问题指的是整数线性规划问题。 其数学模型为 m i n f ( x ) c T x s.t A x b x ≥ 0 x…

opencv的haarcascade_frontalface_default.xml等文件

文章目录 GitHub下载在安装好的OpenCV文件夹下寻找opencv-python中获取 GitHub下载 下载地址&#xff1a;https://github.com/opencv/opencv/tree/master/data/haarcascades 在安装好的OpenCV文件夹下寻找 路径如下&#xff1a; 你安装的opencv路径\OpenCV\opencv\build\et…

亮点!视频云存储/安防监控视频智能分析平台睡岗离岗检测

在生产过程中&#xff0c;未经领导允许的擅自离岗、睡岗会带来很多的潜在危害。TSINGSEE青犀推出的视频云存储/安防监控视频智能分析平台得睡岗离岗检测根据AI视频分析技术建立人工智能算法&#xff0c;对视频画面展开分析与识别。自动识别出人员睡岗、离岗、玩手机与抽烟等动作…

十六、pikachu之SSRF

文章目录 1、SSRF概述2、SSRF&#xff08;URL&#xff09;3、SSRF&#xff08;file_get_content&#xff09; 1、SSRF概述 SSRF(Server-Side Request Forgery&#xff1a;服务器端请求伪造)&#xff1a;其形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能&…

c++ qt--线程(一)(第八部分)

c qt–线程&#xff08;一&#xff09;&#xff08;第八部分&#xff09; 一.进程&#xff08;Process&#xff09; 在任务管理器中的进程页下&#xff0c;可以看到进程&#xff0c;任务管理器将进程分为了三类&#xff0c;应用、后台进程、window进程 应用&#xff1a; 打开…

MyBatis-Plus 总结

MyBatis-Plus简介 官网&#xff1a;https://baomidou.com/ GitHub&#xff1a;https://github.com/baomidou/mybatis-plus Gitee&#xff1a;https://gitee.com/baomidou/mybatis-plus 简介 MyBatis-Plus &#xff08;简称 MP&#xff09;是一个 MyBatis的增强工具&#x…

【C++入门到精通】C++入门 —— 多态(抽象类和虚函数的魅力)

阅读导航 前言一、多态的概念1. 概念2. 多态的特点 二、多态的定义及实现1. 多态的构成条件2. 虚函数3. 虚函数的重写⭕虚函数重写的两个例外1.协变(基类与派生类虚函数返回值类型不同)2.析构函数的重写(基类与派生类析构函数的名字不同) 4. override 和 final&#xff08;C11 …

SLAM从入门到精通(开始篇)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 很多同学喜欢学习linux&#xff0c;但是他们只是把linux当成是一个嵌入式技术在学习&#xff0c;而不是当成工具在使用。平时&#xff0c;要么是自…

appium+python自动化测试

获取APP的包名 1、aapt即Android Asset Packaging Tool&#xff0c;在SDK的build-tools目录下。该工具可以查看apk包名和launcherActivity 2、在android-sdk里面双击SDK-manager,下载buidl-tools 3、勾选build-tools&#xff0c;随便选一个版本&#xff0c;我这里选的是24的版…

YOLOv5、v8改进:CrissCrossAttention注意力机制

目录 1.简介 2. yolov5添加方法&#xff1a; 2.1common.py构建CrissCrossAttention模块 2.2yolo.py中注册 CrissCrossAttention模块 2.3修改yaml文件。 1.简介 这是ICCV2019的用于语义分割的论文&#xff0c;可以说和CVPR2019的DANet遥相呼应。 和DANet一样&#xff0c;…

DBeaver的安装和使用:windows版

DBeaver官网下载地址&#xff1a;https://dbeaver.io/download/ 下载完成后&#xff0c; 进入傻瓜式安装&#xff1a; 这里会进入重复界面&#xff0c;一样点击下一步即可 选择安装目录&#xff0c;尽量不要选C盘&#xff0c; 我的电脑只有c盘&#xff0c; 没办法 等待安装完成…

linux操作系统的权限的深入学习(未完)

1.Linux权限的概念 Linux下有两种用户&#xff1a;超级用户&#xff08;root&#xff09;、普通用户。 超级用户&#xff1a;可以再linux系统下做任何事情&#xff0c;不受限制 普通用户&#xff1a;在linux下做有限的事情。 超级用户的命令提示符是“#”&#xff0c;普通用户…

MVSNet 和 PatchMatchNet 的DTU数据集 几个不同之处 一定要注意

文章目录 1 测试集 数据加载不同2 训练集 数量 分辨率不同 1 测试集 数据加载不同 1.MVSNet 的DTU测试数据集和PatchmatchNet测试数据集不一样&#xff1b; 区别在于数据加载&#xff0c;前者 cams文件最后是最小深度和间隔&#xff0c;后者是最小深度和最大深度。 2 训练集 …

layui框架学习(41:表单模块)

之前的文章《layui框架学习》14-16中介绍了通过预设类及部分layui属性设置表单的外观样式&#xff0c;layui中还提供有表单模块以对表单元素进行各类动态化渲染和相关操作&#xff0c;本文学习并记录表单模块form的常用属性、函数及事件的用法&#xff08;如果内容已在之前文章…

时序预测 | MATLAB实现SSA-XGBoost(麻雀算法优化极限梯度提升树)时间序列预测

时序预测 | MATLAB实现SSA-XGBoost(麻雀算法优化极限梯度提升树)时间序列预测 目录 时序预测 | MATLAB实现SSA-XGBoost(麻雀算法优化极限梯度提升树)时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 Matlab实现SSA-XGBoost时间序列预测&#xff0c;麻…

VS警告 C4819 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失

1、问题 Microsoft visual studio 2019跑仿真的时候出现该警告&#xff0c;在高级保存选项设置编码为Unicode(UTF-8 无签名)还是会有该警告。 2、解决方法 右键项目&#xff0c;打开属性设置&#xff0c;选中&#xff1a;工程 -> 右键选择"属性" -> C/C ->…

JSON文件读写教程【jsoncpp源码编译】【结尾附三方库下载链接】

目录 1 数据下载(jsoncpp源码)2 文件编译3 测试用例4 下载链接:内容: JSON文件的读取与保存可以使用jsoncpp库来实现,这里介绍该库的下载及编译方法。 1 数据下载(jsoncpp源码) 数据下载:Github地址 图1 github源码示意图 2 文件编译 2.1 点击Download ZIP,下载源码。 …

大数据分析与AI在农业领域的应用

文章目录 数据采集与监测数据分析与预测个性化管理与优化决策支持系统结合物联网技术优势与前景 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&#xff1a;Java知识介绍 ✨文章内容&a…

使用ChatGPT给Python代码写单元测试

先写一个简单的python函数&#xff0c;找chatgpt写单元测试&#xff1a; 有一个python函数&#xff0c;请帮忙写单元测试&#xff0c;函数长这样&#xff1a; def test2(a: list, b: list) -> float:"""计算两个坐标的距离:param a list 格式如&#xff1a…