STL之deque容器代码详解

news2025/6/9 19:18:20

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.coloradmin.cn/o/1504285.html

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

相关文章

猫头虎分享已解决Bug || 云服务中断:CloudOutage, CloudProviderError

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

HashMap构造函数

HashMap() /*** Constructs an empty <tt>HashMap</tt> with the default initial capacity* (16) and the default load factor (0.75).* 这是一个默认的构造方法&#xff0c;初始化的容量大小是16&#xff0c;装填因子是0.75* a 装填因子* n 关键字个数* m 总容…

Linux随记(八)

一、crontab运行shell脚本&#xff0c;py脚本 &#xff08;注意事项&#xff09; 情景描述&#xff1a; 目前有个sh脚本他最初大致内容是。 cat t11.sh#!/bin/bash source /etc/profile /bin/python3 /tmp/1.py sh /tmp/1.sh echo -e "$(date %F)" >…

C语言指针、数组学习记录

指针 指针是什么 数据在内存中存放的方式 声明一个变量int i 3;&#xff0c;那么在内存中就会分配一个大小为4字节&#xff08;因为int类型占4字节&#xff09;的内存空间给变量i&#xff0c;这块内存空间存放的数据就是变量i的值。 换句话说就是&#xff0c;在内存中给变…

MySQL--优化(索引)

MySQL–优化&#xff08;索引篇&#xff09; 定位慢查询SQL执行计划索引 存储引擎索引底层数据结构聚簇和非聚簇索引索引创建原则索引失效场景 SQL优化经验 索引 索引&#xff08;index&#xff09;是帮助 MySQL 高效获取数据的数据结构&#xff08;有序&#xff09;。在数据…

【记录37】VueBaiduMap 踩坑一

截图 错误 Error in callback for watcher “position.lng”: “TypeError: Cannot read properties of undefined (reading ‘setPosition’)” 解释 回调观察程序“content”时出错&#xff1a;“TypeError:无法读取未定义的属性&#xff08;读取’setContent’&#xff09;”…

一文掌握:B端系统表单页的作用、组件、设计要点,另附大量案例

Hi&#xff0c;我是贝格前端工场&#xff0c;本篇分享表单页该如何设计&#xff0c;读罢此文让你对表单页有全方位的认识&#xff0c;欢迎点赞评论转发&#xff0c;有需求请私信我们。 一、表单页是什么 表单页是指在Web应用程序中用于收集和提交用户输入数据的页面。它通常由…

基于J2EE的在线考试系统设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术 3 1.1 Java简介 3 1.2 JSP技术 3 1.3 MySQL数据库 4 1.4 B/S结构 4 1.5 本章小结 4 2 系统分析 5 2.1 需求分析 5 2.2 可行性分析 6 2.2.1 技术可行性 6 2.2.2 操作可行性 6 2.2.3 经济可行性 7 2.2.4 法律可行性 7 2.3 系统性能…

邓保康 App 技术支持

邓保康APP功能简介&#xff1a; 这是一款创新&#xff0c;稳定的商业购物型平台app&#xff0c;涵盖同城门店&#xff0c;便捷团购等业务需求。 如果使用过程中有任何疑问可以在帖子中提问&#xff0c;我们会第一时间进行答复和处理。 获得支持&#xff1a; 邮件&#xff1a…

kettle入门一 安装与基本使用

一、kettle概述 1、什么是kettle Kettle是一款开源的ETL工具&#xff0c;纯java编写&#xff0c;可以在Window、Linux、Unix上运行&#xff0c;绿色无需安装&#xff0c;数据抽取高效稳定。 2、Kettle工程存储方式 &#xff08;1&#xff09;以XML形式存储 &#xff08;2&…

Axure基础 各元件的作用及介绍

图像热区 增加按钮或者文本的点击区域&#xff0c;他是透明的&#xff0c;在预览时看不见。 动态面板 用来绘制一下带交互效果的元件&#xff0c;他是动态的&#xff0c;如轮播图&#xff0c;一个动态面板里可以有多个子面板&#xff0c;每一个子面板对应着不同的效果。 他…

像SpringBoot一样使用Flask - 4.拦截器

接上文《像SpringBoot一样使用Flask - 3.蓝图路由Blueprint》&#xff0c;我们已经整理了一个干净的"启动类"&#xff0c;现在要加入一些拦截器&#xff0c;为了方便统一管理。 一、常用的拦截器 # 拦截器 app.before_request def handle_before_request():"&qu…

文献阅读:DEA-Net:基于细节增强卷积和内容引导注意的单图像去雾

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;DEA-Net&#xff1a;基于细节增强卷积和内容引导注意的单图像去雾1、研究背景2、方法提出3、相关知识3.1、DEConv3.3、多重卷积的…

Consul(安装,服务注册与发现,服务配置与动态刷新,配置持久化)

1.下载安装Consul 下载地址:Install | Consul | HashiCorp Developer 解压后只有一个.exe文件&#xff0c;运行后在该文件路径下输入consul --version 启动consul开发模式:consul agent -dev 访问localhost:8500进去consul主页 2.服务注册与发现 官方配置手册:Quick Start :…

进程控制(二) 进程等待与进程替换

目录 一、进程等待 理解进程等待 演示进程等待 获取进程的status 进程等待接口讲解 wait用法​ waitpid用法 等待多进程 基于非阻塞调用的轮询式检测 二、进程程序替换 excel接口 程序替换演示 单进程程序替换 多进程程序替换 程序替换原理 单进程程序替换 多…

Web Worker:JavaScript的后台任务解决方案

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

阿里云服务器ECS u1实例2核4G5M带宽优惠价199元/年性能测评

阿里云服务器ECS u1实例&#xff0c;2核4G&#xff0c;5M固定带宽&#xff0c;80G ESSD Entry盘优惠价格199元一年&#xff0c;性能很不错&#xff0c;CPU采用Intel Xeon Platinum可扩展处理器&#xff0c;购买限制条件为企业客户专享&#xff0c;实名认证信息是企业用户即可&a…

每日OJ题_牛客HJ60 查找组成一个偶数最接近的两个素数

目录 牛客HJ60 查找组成一个偶数最接近的两个素数 解析代码 牛客HJ60 查找组成一个偶数最接近的两个素数 查找组成一个偶数最接近的两个素数_牛客题霸_牛客网 解析代码 #include <cmath> #include <iostream> using namespace std; bool isPrime(int n) {for (…

STM32H750片外QSPI启动配置简要

STM32H750片外QSPI启动配置简要 &#x1f4cd;参考信息源&#xff1a;《STM32H750片外Flash启动(W25Q64JVSIQ)》&#x1f516;本例程基于Keil MDk开发平台。&#x1f341;配置框架&#xff1a; ✨为什么使用要使用QSPI启动方式 不管对于STM32H7系列单片机&#xff0c;还是其他…

BC134 蛇形矩阵

一&#xff1a;题目 二&#xff1a;思路分析 2.1 蛇形矩阵含义 首先&#xff0c;这道题我们要根据这个示例&#xff0c;找到蛇形矩阵是怎么移动的 这是&#xff0c;我们可以标记一下每次移动到方向 我们根据上图可以看出&#xff0c;蛇形矩阵一共有两种方向&#xff0c;橙色…