队列与C++中的std::queue详解(多图超详细)

news2025/1/26 14:40:09

文章目录

    • 队列(Queue)
        • 什么是队列
        • 队列的基本操作和应用
          • 1. 入队
          • 2. 出队
          • 3. 入队出队的复杂度和应用
    • 类模板std::queue
        • 形参T和Container
        • 成员函数
          • 1. 元素访问
          • 2. 容量
          • 3. 队列的修改
    • 用法示例

队列(Queue)

什么是队列

队列就是一种线性的数据结构,它与日常生活中排队的队列相似,即先进先出(LIFO, First In First Out),这点也是它与栈(Stack)的最大不同之处。它的结构类似于下面的容器:

在这里插入图片描述

如上图所示,队列的结构就像一个两端都是开口的容器,一端只负责小球(对应队列中的元素)进入,一个端只负责小球弹出,容器内部的小球无法跳过前面的小球提前弹出。我们将队列的出口端(即队列的头部)叫做队头(front),入口端(即队列的末尾)称为队尾(rear)。

与栈类似,队列的底层数据结构也可以使用数组和链表来实现,具体如下图所示:

在这里插入图片描述

队列的基本操作和应用

队列的基本操作与栈类似,主要是分为入队(enqueue)和出队(dequeue),我们以数组为例,简单描述一下具体过程。

1. 入队

入队就是把新元素放入队列中去,由于队列的数据结构的限制,只允许将新入队元素放入队尾的位置,然后更新队尾的位置,具体过程如下图所示。

在这里插入图片描述

2. 出队

出队就是把队列中的元素移出来,同样的,队列只允许在队列的队头这一侧移出元素,即每次移出的元素就是队头对应的元素,元素移出后,原对头元素的后面一个元素变为新的队头,具体过程如下所示:

在这里插入图片描述

3. 入队出队的复杂度和应用

与栈类似,队列的入队与出队只与队头和队尾的元素相关,不涉及其他元素的移动,因此队列的入队和出队的时间复杂度都是 O ( 1 ) O(1) O(1)

队列先进先出的特性使得其常用于一下场景中:

  • 消息队列:在分布式系统或异步任务处理场景中,消息队列可以用于解耦任务的发布与消费,确保任务能够稳定地进行下去。
  • 程序调度:操作系统、多线程程序、并发网络程序等需要协调多个任务的程序中,通常会使用队列来维护任务的执行顺序,以保证每个任务都能够得到执行。
  • 广度优先搜索:在图论、路径查找等问题中,广度优先搜索算法通常会使用队列来存储待搜索的节点,以确保每一层的所有节点都可以被访问到。
  • 缓存:在许多应用中,缓存通常使用队列来管理缓存项的过期时间和更替策略,使得缓存可以高效地使用有限的内存资源。

类模板std::queue

std::queue类是C++提供的容器适配器,它提供了特定的函数集合,实现了队列的基本功能:FIFO的数据结构,即在容器的尾端推入元素,在首段弹出元素。std::queue类在头文件<queue>中定义,其函数声明如下:

template<
    class T,
    class Container = std::deque<T>
> class queue;

形参T和Container

  • T:存储的元素类型。
  • Container:用于存储元素的底层容器。容器类型必须是序列容器,同时,该容器类型需提供通常语义下的back()、front()、push_back()和pop_front()函数,满足该要求的标准容器有std::deque和std::list,其中默认使用的容器是std::deque。

成员函数

1. 元素访问
  • front:访问队列第一个元素。其函数声明如下:

    reference front();
    const_reference front() const;
    

    该函数返回队列中首个元素的引用,实际上该函数等效的调用的就是存储元素的底层容器(Container)的front()函数。

  • back:访问队列最后一个元素。其函数声明如下:

    reference back();
    const_reference back() const;
    

    该函数返回的是队列末尾元素的引用,实际上该函数等效的调用的就是Container的back()函数。

2. 容量
  • empty:检查队列是否为空。其函数声明如下:

    bool empty() const; // C++20 前
    [[nodiscard]] bool empty() const; //C++20 起
    

    其本质上就是检查Container是否为空,即Container的empty()。如果为空返回true,否则为false。

  • size:返回队列中的元素个数。其函数声明如如下:

    size_type size() const;
    

    同样的,其本质还是返回的是Container的元素个数,即Container的size()。

3. 队列的修改
  • push:向队列的尾部插入元素,对应的就是入队操作。其函数声明如下:

    void push( const value_type& value );
    void push( value_type&& value ); //C++11 起
    
  • emplace:在队列的尾部构造元素,对应的也是入队的操作。其函数声明如下:

    template< class... Args >
    void emplace( Args&&... args );// C++11 起  C++17 前
    template< class... Args >
    decltype(auto) emplace( Args&&... args );// C++17 起
    

    该函数就是将新元素推到队列的尾部,其与push不同的是:该函数是原地构造元素,即不进行移动或复制操作,使用参数直接原地调用元素的构造函数,使得其效率高于push。

  • pop:删除队列首个元素,对应的就是出队操作。其函数声明如下:

    void pop();
    

    该函数移除队列前端的元素,等效的调用了Container的pop_front()函数。

  • swap:交换两个容器的内容。其函数声明如下:

    void swap( queue& other ) noexcept(); //C++11 起
    

    其本质上是交换两个Container中的内容。

用法示例

#include <iostream>
#include <queue>
using namespace std;

void showQueue(string queueName, queue<int>& q) {
    cout << "队列" << queueName << "中元素的数量, 即size() = " << q.size()
        << endl;
    if (!q.empty()) {
        cout << "此时, 队列" << queueName << "不为空,即empty() = false" << endl;
        cout << "队列首位元素,即front() =  " << q.front() << endl;
        cout << "队列首位元素,即back() =  " << q.back() << endl;
    } else {
        cout << "此时, 队列" << queueName << "为空,即empty() = true" << endl;
    }
}

int main() {
    queue<int> q;

    // push()
    q.push(1);
    q.push(2);
    q.push(3);

    cout << "---按顺push元素1、2、3后:\n" << endl;
    showQueue("q", q);

    q.pop();  // 弹出队头元素
    cout << "\n---弹出队头元素3, 即pop()后:\n" << endl;
    showQueue("q", q);

    q.pop();
    cout << "\n---弹出队头元素2, 即pop()后:\n" << endl;
    showQueue("q", q);

    q.pop();
    cout << "\n---弹出队头元素1, 即pop()后:\n" << endl;
    showQueue("q", q);

    queue<int> q1;
    q1.emplace(1);
    q1.emplace(2);
    q1.emplace(3);

    cout << "\n-----------队列q和q1交换前----------" << endl;
    cout << "\nq的状态: " << endl;
    showQueue("q", q);

    cout << "\nq1的状态: " << endl;
    showQueue("q1", q1);

    q1.swap(q);  // s和s1进行交换

    cout << "\n-----------队列q和q1交换后----------\n" << endl;
    showQueue("q", q);

    cout << "\nq1的状态: " << endl;
    showQueue("q1", q1);

    return 0;
}

输出结果:

---按顺push元素1、2、3后:

队列q中元素的数量, 即size() = 3
此时, 队列q不为空,即empty() = false
队列首位元素,即front() =  1
队列首位元素,即back() =  3

---弹出队头元素3, 即pop()后:

队列q中元素的数量, 即size() = 2
此时, 队列q不为空,即empty() = false
队列首位元素,即front() =  2
队列首位元素,即back() =  3

---弹出队头元素2, 即pop()后:

队列q中元素的数量, 即size() = 1
此时, 队列q不为空,即empty() = false
队列首位元素,即front() =  3
队列首位元素,即back() =  3

---弹出队头元素1, 即pop()后:

队列q中元素的数量, 即size() = 0
此时, 队列q为空,即empty() = true

-----------队列q和q1交换前----------

q的状态: 
队列q中元素的数量, 即size() = 0
此时, 队列q为空,即empty() = true

q1的状态: 
队列q1中元素的数量, 即size() = 3
此时, 队列q1不为空,即empty() = false
队列首位元素,即front() =  1
队列首位元素,即back() =  3

-----------队列q和q1交换后----------

队列q中元素的数量, 即size() = 3
此时, 队列q不为空,即empty() = false
队列首位元素,即front() =  1
队列首位元素,即back() =  3

q1的状态: 
队列q1中元素的数量, 即size() = 0
此时, 队列q1为空,即empty() = true

文章首发公众号:iDoitnow如果喜欢话,可以关注一下

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

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

相关文章

单模光纤三维模场分布动画的MATLAB实现

利用MATLAB的动画功能&#xff0c;我们可以把上一篇中绘制的三维分布图变为动画 clear close all clcV 2.4000; U 1.6453; W 1.7473;Npoint 501; Rx 5; Ry 5; x linspace(-Rx,Rx,Npoint); y linspace(-Ry,Ry,Npoint); [X Y] meshgrid(x,y); R sqrt(X.^2Y.^2);E1 …

Android自定义View:超过最大高度时支持滚动并且解决滑动冲突的TextView

VerticalScrollTextView&#xff1a;超过最大高度时支持滚动并且解决滑动冲突的TextView 正如标题所说&#xff0c;这个自定义TextView在它的行数超过最大行数或是高度超过最大高度限制时&#xff0c;会将TextView设置为可纵向滑动的状态&#xff0c;如果没有超过限制&#xf…

python 的APScheduler配置的定时任务会被Miss掉

背景 python 的APScheduler配置的定时任务会被Miss掉&#xff0c;经常在控制台收到一些Miss的告警信息&#xff0c;就觉得是任务太多导致的&#xff0c;为了定位到具体的原因&#xff0c;看了一些源码&#xff0c;了解到了定时任务的6大模块的协同工作模式。异常信息及来源 异…

01.GATK人种系变异最佳实践SnakeMake流程:WorkFlow简介

<~生~信~交~流~与~合~作~请~关~注~公~众~号生信探索> 学习的第一个GATK找变异流程&#xff0c;人的种系变异的短序列变异&#xff0c;包括SNP和INDEL。写了一个SnakeMake分析流程&#xff0c;从fastq文件到最后的vep注释后的VCF文件&#xff0c;关于VCF的介绍可以参考上一…

Windows 安装 GCC

文章目录 GCC 是什么&#xff1f;GCC 和 gcc 什么关系&#xff1f;Windows 安装 GCC选型下载安装配置环境变量验证 参考文献 GCC 是什么&#xff1f; GCC&#xff08;GNU Compiler Collection&#xff09;是一个开源的编译器套件&#xff0c;由 GNU 项目开发和维护。 GNU 编译…

悠可集团再获金鼠标3项大奖,自研营销工具助推全渠道数字营销

5月19日,第14届金鼠标数字营销大赛评选结果揭晓,悠可集团斩获3项大奖,其中悠可集团被评为“年度数字营销杰出代理商”,悠可DTC团队自主研发的智能广告投放引擎Turbo Media及点正科技申报的KOL优先自动化工具均荣获“年度最佳数字营销工具”奖项。 据主办方介绍,本届金鼠标数字营…

java基础 - jvm 堆、栈、方法区 java 内存模型

一、 概览 在进入主题前&#xff0c;我们先了解一些相关的知识&#xff0c;方面后面对运行时数据区进行分类。 进程中&#xff0c;有很多数据是多线程之间共享的&#xff0c;线程在执行时&#xff0c;会先从主存中读取数据&#xff0c;然后复制一份到高速缓存中&#xff0c;当…

【Docker容器】Docker安装Kibana详细步骤(看完这一篇就够啦!)

前言 安装Kibana的版本一定要跟ElaticSearch的版本是一样的&#xff0c;这样才不会容易出问题。 安装ElasticSearch请点击以下链接前去学习。 【Docker容器】Docker安装ElasticSearch详细步骤(看这一篇就够啦&#xff01;) 安装 1.访问镜像官网 https://hub.docker.com/ 搜索…

Java的内存模型(Java Memory Mode,JMM)

并发编程模型的两个关键问题 线程之间如何通信及线程之间如何同步。 线程之间如何通信&#xff1a;共享内存&#xff0c;消息传递线程之间如何同步通信是指线程之间以何种机制来 交换信息同步是指程序中用于控制不同线程间 操作发生相对顺序 的机制在共享内存的并发模型里&a…

【PHP图片托管】免费CFimagehost图床源码搭建私人图床 - 无需数据库

文章目录 1.前言2. CFImagehost网站搭建2.1 CFImagehost下载和安装2.2 CFImagehost网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar临时数据隧道3.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测…

C#入门:编写运行第一个Windows窗体应用程序Helloworld_WinForm

下载及安装Visual Studio的链接&#xff0c;具体见C#入门&#xff1a;编写运行第一个C#程序Helloworld 目录 下载.NET桌面开发组件创建新项目添加控件编辑程序运行查看效果补充 下载.NET桌面开发组件 Visual Studio中需下载安装.NET桌面开发组件。 创建新项目 创建项目&…

【2】Jmeter获取token,模拟多用户并发及token存储文本文件

按以下步骤来&#xff0c;以下各种处理程序的放置位置很重要&#xff01;&#xff01;不然会出现各种问题&#xff1a; 1、setup线程组 前置获取token的接口&#xff08;login&#xff0c;以下都用login表示获取token接口&#xff09;请求&#xff0c;获取类似token等后续需要…

10 个对 Android 开发者有用的 Kotlin 扩展函数 #2

10 个对 Android 开发者有用的 Kotlin 扩展函数 #2 通过出色的 Kotlin 扩展提高您的工作效率 EditText 通过EditText的“text”属性&#xff0c;您可以快速获取EditText中的文本。但是&#xff0c;这个文本是“可编辑”的&#xff0c;因此每次都需要将其转换为字符串才能获…

前端食堂技术周刊第 83 期:TS 5.1 RC、Nuxt 3.5、INP、Knip、管理 GitHub 通知、WebXR

By Midjournery 美味值&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f; 口味&#xff1a;杏花乌龙拿铁 食堂技术周刊仓库地址&#xff1a;https://github.com/Geekhyt/weekly 本期摘要 TypeScript 5.1 RCNuxt 3.5INP 将成为新的 Core Web…

SSM 如何使用 Seata 框架实现分布式事务?

SSM 如何使用 Seata 框架实现分布式事务&#xff1f; 分布式事务是现代分布式系统中必不可少的一部分&#xff0c;而 Seata 框架是一种常用的分布式事务处理方式。在 SSM 框架中&#xff0c;我们可以使用 Seata 框架来管理分布式事务。本文将介绍如何在 SSM 框架中使用 Seata …

好用工具第2期:手机电脑传文件LocalSend

1. 概要 LocalSend 是一个跨平台的 AirDrop替工具软件。 适用于手机电脑之间的数据文件传输&#xff0c;不需要互联网连接或第三方服务器&#xff0c;是局域网本地通信的快速可靠解决方案。 LocalSend 是一个开源项目, 项目地址是: https://github.com/localsend/localsend …

webpack简单的搭建和使用

随便创建一个空的文件夹&#xff0c;例如说&#xff1a;explore 然后我们测试一下我们的node是否存在 可以正确打印出版本 我们再次输入&#xff1a;npm init -y 创建一个package.json文件 出现这样的情况就成功了 然后我们要安装webpack在终端上输入命令&#xff1a; npm i …

辅助生成: 低延迟文本生成的新方向

大型语言模型如今风靡一时&#xff0c;许多公司投入大量资源来扩展它们规模并解锁新功能。然而&#xff0c;作为注意力持续时间不断缩短的人类&#xff0c;我们并不喜欢大模型缓慢的响应时间。由于延迟对于良好的用户体验至关重要&#xff0c;人们通常使用较小的模型来完成任务…

Kotlin SOLID 原则

Kotlin SOLID 原则 许多 Kotlin 开发者并不完全了解 SOLID 原理&#xff0c;即使他们知道&#xff0c;他们也不知道为什么要使用它。您准备好了解所有细节了吗&#xff1f; 介绍 亲爱的 Kotlin 爱好者&#xff0c;您好&#xff01;欢迎来到我的新文章。今天我要讲的是 Kotli…

Qt编程基础 | 第六章-窗体 | 6.2、VS导入资源文件

一、VS导入资源文件 1.1、导入资源文件 步骤一&#xff1a; 将所有图片放到各自文件夹下&#xff0c;并将文件夹拷贝到资源文件&#xff08;.qrc文件&#xff09;的同级目录下&#xff0c;如下&#xff1a; 步骤二&#xff1a; 新建VS项目的时候&#xff0c;系统会自动建好一…