【STL之·容器·queue】

系列文章目录


文章目录

  • 前言
  • 一、概述
    • 1.1 特点:
    • 1.2 queue的工作原理和内部实现
  • 二、基本操作
  • 三、性能分析
    • 3.1 STL队列的时间复杂度和空间复杂度
    • 3.2 STL队列和自定义队列的性能差异
  • 四、实例演示
  • 总结


前言

  • 常见的应用场景包括:

    • 任务调度: 队列可用于任务调度,确保任务按照提交的顺序进行处理。先提交的任务先执行。

    • 广度优先搜索(BFS): 在图算法中,BFS使用队列来管理待访问的节点,确保按照层级的顺序访问节点。

    • 打印队列: 在打印系统中,打印任务被排入队列,以便按照先到先服务的原则进行打印。

    • 缓冲区管理: 队列可以用于管理缓冲区,例如处理网络数据包、操作系统中的缓冲队列等。

    • 消息传递: 队列常用于实现消息传递系统,其中消息按照发送的顺序进行排队和处理。

    • 多线程编程: 在多线程应用程序中,队列可以用于线程之间的通信,充当线程安全的消息传递通道。

    • 实现广告投放系统: 队列可以用于按照广告请求的先后顺序管理广告投放任务。

    • 计算机网络中的数据传输: 在网络通信中,数据包通常以队列的形式进行传输,确保按照发送的顺序接收。

    • 作业调度: 在操作系统中,队列可用于作业调度,确保作业按照提交的先后顺序执行。

    • 排队系统: 在实际生活中的排队系统,如银行、超市等,顾客按照先来先服务的原则排队。


一、概述

C++ STL(Standard Template Library)提供了一个名为queue的容器适配器,它实现了队列的功能,即先进先出(FIFO)的数据结构。

queue容器适配器可以通过包含头文件来使用。它基于一种双端队列(deque)实现,默认情况下,queue容器使用deque作为其底层容器。

注意: 由于queue是一个适配器,它基于底层容器的操作进行实现,因此不支持直接迭代器访问

1.1 特点:

  • 元素按照插入顺序存储,但只能在队列的末尾进行插入操作。
  • 只能在队列的头部进行删除操作。
  • 队列没有随机访问的能力,不能直接访问和修改队列中的任意元素。
  • 队列的大小可以动态增长,没有固定长度的限制。

1.2 queue的工作原理和内部实现

  • STL队列的工作原理是基于一个基础数据结构——双向链表(doubly linked list)来实现的。双向链表是由一个个节点组成的,每个节点包含一个元素和指向前一个节点和后一个节点的指针。

  • STL队列的内部实现使用了双向链表作为底层数据结构,具体来说,是以一个双向链表的尾部作为队列的头部(front),而链表的头部作为队列的尾部(back)。这样设计的目的是为了高效地进行元素的插入和删除操作。

  • 当向队列中插入一个元素时,该元素将被添加到双向链表的末尾,并更新队列的尾部指针。而从队列中删除元素时,则是从链表的头部删除第一个元素,并更新队列的头部指针。

  • 通过这种设计,STL队列可以快速执行插入和删除操作,而且不需要移动整个队列中的元素,因为它只需要更新头部和尾部指针即可。这种设计保证了队列的先进先出的特性,并提供了高效的性能。

此外,STL队列还提供了其他一些常用的功能,如判断队列是否为空、获取队列中元素的个数等。这些功能都是基于底层的双向链表实现的。

二、基本操作

方法描述
push(element)将元素element添加到队列的末尾。
emplace(element)将元素element添加到队列的末尾。
pop()移除队列的第一个元素。
front()返回队列的第一个元素,但不移除它。
back()返回队列的最后一个元素,但不移除它。
empty()检查队列是否为空,如果为空则返回true,否则返回false。
size()返回队列中元素的个数。

注意: push是得传入得对象先得造好,再复制过去插入;而emplace则可以自己拿到构造对象所需得元素构造出来,直接插入即可。emplace相比于push省去了复制这步,即使用emplace这种操作会更节省内存

三、性能分析

3.1 STL队列的时间复杂度和空间复杂度

STL队列的时间复杂度和空间复杂度如下:

  1. 入队操作(push)的时间复杂度为O(1),因为只需要在队尾添加元素。
  2. 出队操作(pop)的时间复杂度也为O(1),因为只需要在队首删除元素。
  3. 查看队首元素(front)的时间复杂度为O(1),因为只需要返回队首元素。
  4. 查看队尾元素(back)的时间复杂度为O(1),因为只需要返回队尾元素。

总的来说,STL队列的操作都是常数时间复杂度,即O(1)。

空间复杂度方面,STL队列的空间复杂度取决于队列中元素的个数,即为O(n),其中n为队列中的元素个数。

3.2 STL队列和自定义队列的性能差异

STL队列和自定义队列的性能差异在很大程度上取决于具体的实现方式和使用场景。以下是一些可能的差异:

  1. 内存管理:STL队列使用动态分配的内存来存储元素,这意味着在插入和删除元素时,可能需要频繁地重新分配和复制元素。相比之下,自定义队列可以使用静态数组或链表来存储元素,从而避免了频繁的内存分配和复制操作。
     
  2. 容量管理:STL队列具有自动扩容的能力,可以动态调整队列的大小以适应元素的变化。自定义队列可能需要手动管理容量,当队列满时,需要手动扩容。
     
  3. 性能优化:STL队列是经过优化和测试的标准容器,在大多数情况下,它具有较好的性能。自定义队列的性能则取决于具体的实现方式和算法的选择,可能需要更多的优化来达到相同的性能水平。

总的来说,STL队列在大多数情况下具有较好的性能和可靠性,尤其适用于一般的应用场景。然而,当需要对队列的性能进行特定的优化或者对内存管理有特殊要求时,自定义队列可能更加适合。

四、实例演示

示例1:

基本操作
queue<int> q;q.push(10);q.emplace(20);q.emplace(30);cout << q.empty() << endl;cout << q.size() << endl;cout << q.front() << endl;cout << q.back() << endl;q.pop();cout << q.front() << endl;

运行结果:
在这里插入图片描述
示例2:

常见的队列操作,如生产者-消费者模型
#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>std::queue<int> q;
std::mutex mtx;
std::condition_variable cv;void producer() {for (int i = 0; i < 10; ++i) {std::this_thread::sleep_for(std::chrono::seconds(1));std::lock_guard<std::mutex> lock(mtx);q.push(i); // 生产者将数据压入队列std::cout << "Producer produced: " << i << std::endl;cv.notify_all(); // 通知消费者有数据可取}
}void consumer() {while (true) {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [] { return !q.empty(); }); // 消费者等待直到队列非空int data = q.front();q.pop(); // 消费者从队列取出数据std::cout << "Consumer consumed: " << data << std::endl;lock.unlock();std::this_thread::sleep_for(std::chrono::seconds(2));}
}int main() {std::thread producerThread(producer);std::thread consumerThread(consumer);producerThread.join();consumerThread.join();return 0;
}

总结

优点和适用场景:

1. 高效性: STL队列的操作是基于deque实现的,deque是一种双端队列,插入和删除操作都是高效的。在尾部插入元素和删除元素的时间复杂度都是常数时间O(1)。

2. 先进先出(FIFO): STL队列是一种先进先出的数据结构,只能在队首移除元素,在队尾插入元素。这种特性适用于一些需要顺序处理的场景,比如任务调度、消息传递等。

3. 线程安全: STL队列在多线程环境下可以通过加锁来实现线程安全。对于需要在多个线程中同时访问的情况,可以使用STL队列来实现线程间的消息传递或任务调度。

4. 适用于BFS算法: nSTL队列适用于广度优先搜索(BFS)算法的实现。在BFS算法中,需要将遍历过的节点按照一定的顺序保存起来,以便后续处理。STL队列能够很好地满足这个需求。

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

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

相关文章

Dav_笔记11:SQL Tuning Overview-sql调优 之 5

构建SQL测试用例 对于许多与SQL相关的问题&#xff0c;获得可重现的测试用例可以更轻松地解决问题。从11g第2版&#xff08;11.2&#xff09;开始&#xff0c;Oracle数据库包含SQL测试用例构建器&#xff0c;它可以自动完成收集和复制尽可能多的有关问题及其发生环境的信息的难…

CIT分布式版本控制系统

一、GIT概述 在Linux虚拟机中配置DNS主从&#xff08;Master-Slave&#xff09;服务&#xff0c;通常涉及到BIND&#xff08;Berkeley Internet Name Domain&#xff09;软件的安装、主服务器&#xff08;Master&#xff09;的配置以及从服务器&#xff08;Slave&#xff09;的…

MFC开发,自定义消息

在MFC开发中&#xff0c;主要核心机制就是消息机制。QT与之类似的机制就是信号与槽。QT中的信号与槽是非常容易自定义的&#xff0c;MFC也是如此&#xff0c;自定义也是比较方便&#xff0c;况且自定义消息或者控件在整个GUI图形化界面开发中也是非常重要的部分&#xff0c;上篇…

【python】python销售数据分析可视化(源码+论文+数据集)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

记忆、思维、问题解决与创造、想象

记忆 思维 问题解决与创造性 想象

食家巷一窝丝:丝丝入味,口口留香

在美食的大观园中&#xff0c;有一种独特的美味让人难以忘怀&#xff0c;那就是食家巷一窝丝。食家巷一窝丝&#xff0c;以其精湛的制作工艺和独特的口感&#xff0c;成为了众多美食爱好者的心头好。 当你第一眼看到一窝丝&#xff0c;定会被它那精致的外形所吸引。纤细如丝的面…

nodejs - express 学习笔记

express 是一个基于 Node.js 平台的极简、灵活的 WEB 应用开发框架&#xff0c;官方网址&#xff1a;https://www.expressjs. com.cn/ 简单来说&#xff0c;express 是一个封装好的工具包&#xff0c;封装了很多功能&#xff0c;便于我们开发 WEB 应用&#xff08;HTTP 服务&am…

如何恢复最近删除的文件?5种简单方法!

数据丢失在我们的工作生活中经常发生。当你决定清理硬盘或U盘时&#xff0c;你会删除一些文件夹或文件。如果你通过右键单击删除文件&#xff0c;则可以很容易从回收站恢复已删除的文件。但是&#xff0c;如果你按Shift Delete键、清空回收站或删除大于8998MB的大文件夹&#…

哪些ESP32系列芯片具有双道通I2S和PDM RX?

ESP32芯片选择&#xff1a; 需要使用2个通道IIS的&#xff0c;只能选择ESP32、ESP32-S3、ESP32-P4三种之一&#xff0c;需要适应PDM RX时也只能选择这3个芯片系列。 芯片I2S 标准PDM TXPDM RXTDMADC/DACLCD/摄像头ESP32I2S 0/1I2S 0I2S 0无I2S 0I2S 0ESP32-S2I2S 0无无无无I2…

[C++实战]日期类的实现

&#x1f496;&#x1f496;&#x1f496;欢迎来到我的博客&#xff0c;我是anmory&#x1f496;&#x1f496;&#x1f496; 又和大家见面了 欢迎来到C探索系列 作为一个程序员你不能不掌握的知识 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成本搭建个人网站…

MySQL中不等于筛选时会漏掉null值的问题

一、问题描述 MySQL中使用不等于进行筛选数据时&#xff0c;若筛选值为null&#xff0c;则该条数据不会被选中&#xff0c;如何解决该问题&#xff1f; 表示不等于的方式如下&#xff1a; ! <> not in二、案例验证 1、创建数据表 -- ---------------------------- -…

20240725java的Controller、DAO、DO、Mapper、Service层、反射、AOP注解等内容的学习

在Java开发中&#xff0c;‌controller、‌dao、‌do、‌mapper等概念通常与MVC&#xff08;‌Model-View-Controller&#xff09;‌架构和分层设计相关。‌这些概念各自承担着不同的职责&#xff0c;‌共同协作以构建和运行一个应用程序。‌以下是这些概念的解释&#xff1a;‌…

Nestjs使用Redis的最佳实践

前几天在项目中有用到Redis JWT实现服务端对token的主动删除(退出登录功能)。故此介绍下如何在Nestjs中使用Redis&#xff0c;并做下总结。 知识准备 了解Redis - 网上很多简介。了解Nestjs如何使用jwt生成token - 可移步看下我之前的文章 效果展示 一、mac安装与使用 示…

Typora笔记上传到CSDN

1.Typora 安装 Typora链接&#xff1a;百度网盘 提取码&#xff1a;b6d1 旧版本是不需要破解的 后来的版本比如1.5.9把放在typora的根目录下就可以了 2.上传到CSDN 步骤 csdn 写文章-使用MD编辑器-导入本地md文件即可 问题 图片没法显示 原因 图片的链接是本地的 当然没法…

pyqt designer使用spliter

1、在designer界面需要使用spliter需要父界面不使用布局&#xff0c;减需要分割两个模块选中&#xff0c;再点击spliter分割 2、在分割后&#xff0c;再对父界面进行布局设置 3、对于两边需要不等比列放置的&#xff0c;需要套一层 group box在最外层进行分割

模板编程中二义性问题

前言 菱形继承是 一个常见的二义性问题&#xff0c;这个问题在模板元编程中也很容易隐晦的存在 错误示例代码 #include <iostream>template <int N> struct A {int getN() { return N; } };template <int N> struct B : A<N % 2>, B<N / 2> {…

创建文件到底发生了什么?

为什么要浅浅探究这个问题&#xff1f; 大家大部分时间的工作其实都是写业务层的”CURD“&#xff0c;而真正陪伴在我们身边的计算机底层原理则不再有那么多好奇心去探究了。这篇文章旨在抛砖引玉&#xff0c;也许大家在空闲的时间里&#xff0c;也能够去探求自己以前一直想知…

AcWing最长连续不重复子序列

哈希表就完事儿了&#xff0c;key是a[j],value是a[j]出现次数 i丢到前面&#xff0c;j丢到后面&#xff0c;然后j往后面遍历&#xff0c;每次记录a[j]出现次数 m a p [ a [ j ] ] map[a[j]] map[a[j]]&#xff0c;如果a[j]出现次数2次及其以上 m a p [ a [ j ] ] > 1 map[a[…

信号量的实例

例题&#xff1a; 进程 a 和进程 b 模拟访问打印机&#xff0c;进程 a 输出第一个字符‘ a’表示开始使用打印 机&#xff0c;输出第二个字符‘ a’表示结束使用&#xff0c; b 进程操作与 a 进程相同。&#xff08;由于打印机同一时刻 只能被一个进程使用&#xff0c;所以输出…

【数据结构--排序】

目录 一、排序概述1.1、排序的相关定义1.2、排序用到的结构与函数 二、常见排序算法2.1、冒泡算法&#xff08;交换顺序&#xff09;&#xff08;1&#xff09;算法&#xff08;2&#xff09;性能分析 2.2、简单选择排序&#xff08;1&#xff09;算法&#xff08;2&#xff09…