STL之deque容器代码详解

1 基础概念

功能:

双端数组,可以对头端进行插入删除操作。

deque与vector区别:

  • vector对于头部的插入删除效率低,数据量越大,效率越低。

  • deque相对而言,对头部的插入删除速度回比vector快。

  • vector访问元素时的速度会比deque快,这和两者内部实现有关。

在这里插入图片描述

deque内部工作原理:

  • deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据。

  • 中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间。

  • deque容器的迭代器也是支持随机访问的。

在这里插入图片描述

2 代码解释

Talk is cheap, show me the code.

#include<iostream>
using namespace std;
#include<deque>
#include<algorithm>void printDeque(const deque<int>& dd)
{//注意这里的只读迭代器的操作for (deque<int>::const_iterator it = dd.begin(); it != dd.end(); it++){cout << *it << " ";}cout << endl;
}/*
构造函数原型:
deque<T> deqT; //默认构造形式
deque(beg, end); //构造函数将[beg, end)区间中的元素拷贝给本身。
deque(n, elem); //构造函数将n个elem拷贝给本身。
deque(const deque &deq); //拷贝构造函数
*/void test01()
{deque<int> d1;for (int i = 0; i < 10; i++){d1.push_back(i);}printDeque(d1);deque<int> d2(d1.begin(), d1.end());printDeque(d2);deque<int> d3(10, 88);printDeque(d3);deque<int> d4(d3);printDeque(d4);}/*
赋值函数原型:
deque& operator=(const deque &deq); //重载等号操作符
assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem); //将n个elem拷贝赋值给本身。
*/void test02()
{deque<int> d1;for (int i = 0; i < 10; i++){d1.push_back(i);}deque<int> d2;d2 = d1;printDeque(d2);deque<int> d3;d3.assign(d2.begin(), d2.end());printDeque(d3);deque<int> d4;d4.assign(10, 88);printDeque(d4);
}/*
大小操作函数原型:
deque.empty(); //判断容器是否为空
deque.size(); //返回容器中元素的个数
deque.resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
*/// 我们发现跟vector相比没有了capacity容量相关的操作,因为可以无限地扩展,只需要有一段地址来维护空间void test03()
{deque<int> d1;for (int i = 0; i < 10; i++){d1.push_back(i);}printDeque(d1);if (d1.empty()){cout << "EMPTY" << endl;}else{cout << d1.size() << endl;}d1.resize(20, 999);printDeque(d1);
}/*
插入和删除函数原型:
两端插入操作:
push_back(elem); //在容器尾部添加一个数据
push_front(elem); //在容器头部插入一个数据
pop_back(); //删除容器最后一个数据
pop_front(); //删除容器第一个数据
指定位置操作:
insert(pos,elem); //在pos位置插入一个elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem); //在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end); //在pos位置插入[beg,end)区间的数据,无返回值。
clear(); //清空容器的所有数据
erase(beg,end); //删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos); //删除pos位置的数据,返回下一个数据的位置。
*/void test04()
{deque<int> d1;d1.push_back(100);d1.push_back(100);d1.push_back(100);d1.push_back(100);d1.push_back(100);d1.push_back(100);printDeque(d1);d1.push_front(200);printDeque(d1);d1.pop_back();printDeque(d1);d1.pop_front();printDeque(d1);d1.insert(d1.begin() + 2, 5, 1000);printDeque(d1);d1.insert(d1.end() - 1, d1.begin(), d1.end());printDeque(d1);d1.erase(d1.begin()+1);printDeque(d1);d1.clear();printDeque(d1);}/*
数据存取函数原型:
at(int idx); //返回索引idx所指的数据
operator[]; //返回索引idx所指的数据
front(); //返回容器中第一个数据元素
back(); //返回容器中最后一个数据元素
*/void test05()
{deque<int> d1;for (int i = 0; i < 10; i++){d1.push_back(i);}printDeque(d1);cout << d1.at(2) << endl;cout << d1[2] << endl;cout << d1.front() << endl;cout << d1.back() << endl;
}/*
排序算法:
sort(iterator beg, iterator end) //对beg和end区间内元素进行排序
*/void test06()
{deque<int> d1;d1.push_back(10);d1.push_back(20);d1.push_back(15);d1.push_front(89);d1.push_front(78);d1.push_front(99);printDeque(d1);sort(d1.begin(), d1.end());printDeque(d1);
}int main()
{test01();test02();test03();test04();test05();test06();system("pause");return 0;
}

3 应用场景

C++标准模板库(STL)中的deque(双端队列)容器是一种支持在两端高效插入和删除操作的数据结构。它在实际项目中有许多应用场景,其中一些例子包括:

  1. 任务调度队列: 在多线程或并发编程中,deque可以用作任务调度队列。新任务可以在队列的前端或后端插入,而工作线程可以从队列的另一端获取任务执行。这种方式允许高效的任务调度和分发。

    #include <deque>
    #include <mutex>
    #include <thread>std::deque<Task> taskQueue;
    std::mutex queueMutex;void AddTask(const Task& task) {std::lock_guard<std::mutex> lock(queueMutex);taskQueue.push_back(task);
    }Task GetTask() {std::lock_guard<std::mutex> lock(queueMutex);Task task = taskQueue.front();taskQueue.pop_front();return task;
    }
    
  2. 实时数据流处理: 在需要高性能数据流处理的应用中,deque可以用于缓存数据,支持快速的数据插入和删除。这对于实时数据处理系统(如金融数据处理或传感器数据处理)非常有用。

    #include <deque>
    #include <iostream>void ProcessData(std::deque<Data>& dataQueue) {// 实时数据处理逻辑while (!dataQueue.empty()) {Data currentData = dataQueue.front();dataQueue.pop_front();// 处理数据...}
    }
    
  3. 存储历史记录: 在需要保留最近N个元素的场景中,deque可以用于实现一个固定大小的历史记录缓存。新元素可以从一端插入,而旧元素可以从另一端删除,以保持缓存的大小。

    #include <deque>
    #include <iostream>const int MaxHistorySize = 10;
    std::deque<Record> historyDeque;void AddToHistory(const Record& record) {historyDeque.push_back(record);if (historyDeque.size() > MaxHistorySize) {historyDeque.pop_front();}
    }
    
  4. 实现高效的双端队列: 当需要在两端执行频繁插入和删除操作时,使用deque而不是vector可能更为高效,因为deque的设计允许在两端进行快速操作,而vector在插入或删除头部元素时的性能较差。

总的来说,deque是一个灵活的数据结构,适用于许多不同的应用场景,其中需要高效支持两端操作的情况。

4 实际用例

下面是一个简单的示例,演示了使用deque相对于vector在频繁插入和删除操作时的优势。这个示例模拟一个实时日志系统,其中日志消息被不断添加到队列,并定期删除旧的日志消息,以保持队列的大小。

#include <iostream>
#include <deque>
#include <ctime>
#include <cstdlib>struct LogMessage {std::string message;time_t timestamp;
};class RealTimeLogger {
public:void AddLog(const std::string& message) {LogMessage log;log.message = message;log.timestamp = std::time(nullptr);logQueue.push_back(log);}void PruneOldLogs() {const int MaxLogCount = 5;while (logQueue.size() > MaxLogCount) {logQueue.pop_front();}}void PrintLogs() {for (const auto& log : logQueue) {std::cout << "[" << log.timestamp << "] " << log.message << std::endl;}std::cout << std::endl;}private:std::deque<LogMessage> logQueue;
};int main() {RealTimeLogger logger;// 模拟日志生成for (int i = 0; i < 10; ++i) {logger.AddLog("Log message #" + std::to_string(i));logger.PruneOldLogs();logger.PrintLogs();}return 0;
}

在这个示例中,RealTimeLogger类使用deque作为存储日志消息的容器。在每次添加日志消息时,它会执行PruneOldLogs方法来删除旧的消息,以保持队列的大小。由于deque支持在两端高效地进行插入和删除操作,这个实现在频繁添加和删除日志消息时的性能表现更好。

当使用vector时,由于在头部删除元素的代价相对较高,性能可能不如deque。在实际项目中,这种优势可能在需要处理大量实时数据的场景下更为明显,例如日志记录、事件处理等。

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

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

相关文章

Unity Shader实现UI流光效果

效果&#xff1a; shader Shader "UI/Unlit/Flowlight" {Properties{[PerRendererData] _MainTex("Sprite Texture", 2D) "white" {}_Color("Tint", Color) (1, 1, 1, 1)[MaterialToggle] PixelSnap("Pixel snap", float…

简洁的在线观影开源项目

公众号&#xff1a;【可乐前端】&#xff0c;每天3分钟学习一个优秀的开源项目&#xff0c;分享web面试与实战知识。 每天3分钟开源 hi&#xff0c;这里是每天3分钟开源&#xff0c;很高兴又跟大家见面了&#xff0c;今天介绍的开源项目简介如下&#xff1a; 仓库名&#xff1…

海外媒体发稿:7种媒体套餐推广策略解析-华煤舍

有效的媒体宣传策略对于产品或服务的推广至关重要。本文将介绍7种媒体套餐推广策略&#xff0c;帮助您惊艳市场&#xff0c;并取得成功。以下是每种策略的拆解描述&#xff1a; 1. 广告投放 广告投放是最常见的宣传手段之一。通过在各种媒体平台上购买广告&#xff0c;如电视、…

Web渗透测试流程

什么是渗透测试 渗透测试 (penetration test),是通过模拟恶意黑客的攻击方法&#xff0c;来评估计算机网络系统安全的一种评估方法。这个过程包括对系统的任何弱点、技术缺陷或漏洞的主动分析&#xff0c;这个分析是从一个攻击者可能存在的位置来进行的&#xff0c;并且从这个…

linux 查看打开使用了哪些端口

你可以使用 netstat 命令来查看Linux系统中正在使用的端口。例如&#xff0c;要查看所有正在使用的TCP和UDP端口&#xff0c;你可以运行&#xff1a; sudo netstat -tulpn如果你只想查看所有正在使用的TCP端口&#xff0c;你可以运行&#xff1a; sudo netstat -tpln 如果你只…

全网最最最详细centos7如何安装docker教程

在CentOS 7上安装Docker主要包括以下步骤&#xff1a; 1. 卸载旧版本的Docker 首先&#xff0c;需要确保系统上没有安装旧版本的Docker。可以通过以下命令来卸载它们&#xff1a; sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-late…

【Linux】编译器-gcc/g++使用

个人主页 &#xff1a; zxctscl 文章封面来自&#xff1a;艺术家–贤海林 如有转载请先通知 文章目录 1. 前言2. 初见gcc和g3. 程序的翻译过程3.1 预处理3.1.1 宏替换 去注释 头文件展开3.1.2 条件编译 3.2 编译3.3 汇编3.4 链接 4. 链接4.1 动态链接4.2 静态链接 1. 前言 在之…

吴恩达机器学习-可选实验:特征缩放和学习率(多变量)

文章目录 目标工具概念问题陈述数据集多变量梯度下降学习率a9.9e-7a9e-7a1e-7 特征缩放实现 恭喜致谢 目标 在本实验中&#xff0c;你将: 利用在上一个实验中开发的多变量例程对具有多个特征的数据集运行梯度下降探讨学习率alpha对梯度下降的影响通过使用z-score归一化的特征…

域控操作十:安装包exe转msi软件下发

需要的文件 Advanced Installer 软件用来将exe转换成msi因为域控只能下发msi格式 一个exe安装包这里拿微信举例 一个没有密码的共享文件夹 1.exe转MSI 2&#xff0c;开始下发 服务器和用户刷新策略 #完成

某品零食交易平台设计与实现|基于springboot+ Mysql+Java的某品交易平台设计与实现(源码+数据库+文档+PPT)

目录 基于springboot MysqlJava的某品交易平台设计与实现 摘 要 系统详细设计 数据库设计 论文参考 源码获取 文末获取源码联系 基于springboot MysqlJava的某品交易平台设计与实现 摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的…

html--彩虹爱心

文章目录 js内容cssreset.min.cssstyle.css html内容 js内容 const colors ["#e03776","#8f3e98","#4687bf","#3bab6f","#f9c25e","#f47274"]; const SVG_NS http://www.w3.org/2000/svg; const SVG_XLINK &q…

Spring Boot 多环境配置

Spring Boot 多环境配置 在现代的软件开发中&#xff0c;通常需要将应用程序部署到不同的环境中&#xff0c;如开发环境、生产环境和测试环境等。每个环境可能需要不同的配置参数&#xff0c;例如数据库连接信息、日志级别等。在 Spring Boot 中&#xff0c;我们可以通过简单的…

智慧库室管控系统-智慧枪弹管控系统

项目背景&#xff1a; 针对部队装备管理现状&#xff0c;部队在进行硬件系统建设的同时&#xff0c;需通过装备管理系统软件的建设&#xff0c;综合集成监控、报警、出入库、信息发布、库管理、监测、防护等系统&#xff0c;对装备进行立体监控、实时预警、快速处理&#xff0…

springboot255基于spring boot的疫情信息管理系统

疫情信息管理系统的设计与实现 摘要 近年来&#xff0c;信息化管理行业的不断兴起&#xff0c;使得人们的日常生活越来越离不开计算机和互联网技术。首先&#xff0c;根据收集到的用户需求分析&#xff0c;对设计系统有一个初步的认识与了解&#xff0c;确定疫情信息管理系统…

【每日刷题】栈与队列-LC394、LC347、LC215

题外话&#xff1a;感觉脑子没长到栈这块…最近刷栈的题都好难啊…哭哭…坚持坚持&#xff01;多刷几遍就好了&#xff01;&#xff01; 1. LC394.字符串解码 题目链接 先说数据结构。 维护两个栈&#xff1a;一个栈存之前的字符串&#xff0c;另一个栈存之后的字符串的重复…

基于命名实体链接的事件抽取与知识图谱在电商领域的应用

开源项目推荐 多模态AI能力引擎平台: 免费的自然语言处理、情感分析、实体识别、图像识别与分类、OCR识别、语音识别接口&#xff0c;功能强大&#xff0c;欢迎体验。 多模态AI能力引擎平台: 免费的自然语言处理、情感分析、实体识别、图像识别与分类、OCR识别、语音识别接口…

mysql | 查询数据的过程|优化-->索引 |存储引擎

查询的过程 首先确认mysql 服务器是否启动 systemctl mysqld status 登录连接 mysql -h i p − u ip -u ip−uuser -p (-h 指定服务器ip -u 指定用户名 -p 指定密码) mysql 数据包 经过抓包分析&#xff08;mysql包其实就是基于tcp协议 3306端口) 传输采用mysql 协议&#xff0…

云原生构建 微服务、容器化与容器编排

第1章 何为云原生&#xff0c;云原生为何而生 SOA也就是面向服务的架构 软件架构的发展主要经历了集中式架构、分布式架构以及云原生架构这几代架构的发展。 微服务架构&#xff0c;其实是SOA的另外一种实现方式&#xff0c;属于SOA的子集。 在微服务架构下&#xff0c;系统…

Web本体语言OWL

语义网&#xff08;Semantic Web&#xff09;&#xff1a; 语义网是万维网联盟&#xff08;W3C&#xff09;提出的一种愿景&#xff0c;旨在增强现有Web的表达能力和智能处理能力&#xff0c;通过标准化的技术手段赋予网络数据更加精确和可计算的语义&#xff0c;使得机器能够…

ReactNative项目构建分析与思考之react-native-gradle-plugin

前一段时间由于业务需要&#xff0c;接触了下React Native相关的知识&#xff0c;以一个Android开发者的视角&#xff0c;对React Native 项目组织和构建流程有了一些粗浅的认识&#xff0c;同时也对RN混合开发项目如何搭建又了一点小小的思考。 RN环境搭建 RN文档提供了两种…