【C++】深入理解 C++ 优先级队列、容器适配器与 deque:实现与应用解析

news2024/11/17 19:41:35

个人主页: 起名字真南的CSDN博客

个人专栏:

  • 【数据结构初阶】 📘 基础数据结构
  • 【C语言】 💻 C语言编程技巧
  • 【C++】 🚀 进阶C++
  • 【OJ题解】 📝 题解精讲

目录

  • 前言
  • 📌 1. 优先级队列、容器适配器和 `deque` 概述
    • ✨1.1 什么是优先级队列?
    • ✨ 1.2 容器适配器与 `deque`
  • 📌 2. `deque` 的特点与基本操作
    • ✨2.1 特点
    • ✨2.2 基本操作
  • 📌 3. 容器适配器的类型与实现原理
  • 📌 4. `priority_queue` 的基本使用
  • 📌 5. 实际应用场景:任务调度与路径搜索
    • ✨5.1 优先级队列在任务调度中的应用
    • ✨ 5.2 `deque` 在滑动窗口问题中的应用
  • 📌 6. 总结与常见问题解答
    • ✨ 6.1 常见问题
  • 总结

前言

在 C++ 标准库中,优先级队列(priority_queue)是一种容器适配器,特别适合处理需要频繁访问最大值或最小值的数据集。同时,双端队列 deque 也是一种灵活的标准容器,支持高效的头尾插入、删除操作,被广泛用于实现队列、栈等数据结构。本文将深入讲解优先级队列、deque 及其在容器适配器中的应用。


📌 1. 优先级队列、容器适配器和 deque 概述

✨1.1 什么是优先级队列?

优先级队列是一种基于优先级的特殊队列。默认情况下,C++ 的 priority_queue 是最大堆,出队时总是返回最大元素。实现优先级队列的底层容器通常是 vectordeque,其中 deque 是标准库提供的双端队列容器,支持高效的头尾插入和删除。

✨ 1.2 容器适配器与 deque

C++ 容器适配器包括 stackqueuepriority_queue,它们对底层容器进行封装,提供栈、队列等结构的特定接口。dequequeuestack 默认使用的底层容器,提供两端的灵活操作。


📌 2. deque 的特点与基本操作

在这里插入图片描述

deque(双端队列)是 C++ 中的一种序列容器,支持在两端快速插入和删除。deque 的实现类似一个分段的动态数组,因此具备更灵活的内存管理方式,可以在前后两端动态扩展。

✨2.1 特点

  • 双端插入与删除:支持在头尾两端快速插入和删除,效率接近 O(1)
  • 动态扩展:不像 vector 只能从尾部扩展,deque 可以在头部或尾部自由扩展。
  • 支持随机访问:与 vector 类似,可以通过索引访问任意位置的元素,但相比 vector 速度稍慢。

✨2.2 基本操作

#include <iostream>
#include <deque>

void deque_example() {
    std::deque<int> dq;

    // 在尾部插入
    dq.push_back(10);
    dq.push_back(20);

    // 在头部插入
    dq.push_front(5);

    // 访问元素
    std::cout << "Front: " << dq.front() << std::endl;  // 5
    std::cout << "Back: " << dq.back() << std::endl;    // 20

    // 删除头尾元素
    dq.pop_front();
    dq.pop_back();

    // 遍历
    std::cout << "Elements: ";
    for (int elem : dq) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;
}

int main() {
    deque_example();
    return 0;
}

输出

Front: 5
Back: 20
Elements: 10 

代码解析

  • push_backpush_front:分别在尾部和头部插入元素。
  • pop_backpop_front:分别从尾部和头部删除元素。
  • frontback:访问头部和尾部的元素。

📌 3. 容器适配器的类型与实现原理

C++ 容器适配器使用底层容器来构建特定的数据结构,例如栈、队列和优先级队列。以下是容器适配器的类型及默认底层容器:

  • stack:默认使用 deque 实现的后进先出(LIFO)数据结构,也支持 vector
  • queue:使用 deque 实现的先进先出(FIFO)数据结构,提供 pushpopfrontback 操作。
  • priority_queue:通常使用 vectordeque 实现,提供最高优先级元素的访问和出队操作。

使用 deque 作为底层容器时,可以灵活利用其双端插入和删除的特性。


📌 4. priority_queue 的基本使用

在这里插入图片描述

priority_queue 默认是最大堆,每次 pop 操作返回当前的最大值。其底层容器通常使用 vector,但 deque 也可以用作其底层容器。
如果我们想让他最小堆可以在传入参数的时候传入 greater

#include <iostream>
#include <queue>
#include <vector>
#include <functional>  // std::greater

int main()
{
	std::priority_queue<int> pq_max;
	pq_max.push(10);
	pq_max.push(20);
	pq_max.push(30);
	pq_max.push(40);

	while (!pq_max.empty())
	{
		cout << pq_max.top() << " ";
		pq_max.pop();
	}
	cout << endl;
	std::priority_queue<int,vector<int>,greater<int>> pq_min;
	pq_min.push(10);
	pq_min.push(20);
	pq_min.push(30);
	pq_min.push(40);
	while (!pq_min.empty())
	{
		cout << pq_min.top() << " ";
		pq_min.pop();
	}
	cout << endl;
	return 0;
}

输出

40 30 20 10
10 20 30 40

📌 5. 实际应用场景:任务调度与路径搜索

✨5.1 优先级队列在任务调度中的应用

在任务调度中,priority_queue 可以用来根据任务优先级调度任务。例如,操作系统内核中的进程管理通常需要根据优先级选择任务执行。可以使用 priority_queue 来存储任务,每次从队列中取出最高优先级的任务执行。

✨ 5.2 deque 在滑动窗口问题中的应用

deque 因其双端特性,被广泛用于解决滑动窗口问题。例如,在一个数组中找到滑动窗口的最大值,可以通过 deque 快速实现。每当窗口向前滑动时,使用 dequepush_backpop_front 可以高效地更新窗口中的最大值。


📌 6. 总结与常见问题解答

通过本文的介绍,我们全面了解了 priority_queuedeque 的实现与应用场景。以下是一些常见问题解答:

✨ 6.1 常见问题

  1. dequevector 的区别是什么?

    • deque 支持在两端高效插入和删除,而 vector 仅支持尾部的快速插入与删除。
  2. 为什么 priority_queue 默认使用 vector

    • priority_queue 主要关注堆操作的效率,而 vector 是一个连续内存容器,适合在堆排序中实现高效的随机访问。
  3. deque 可以用在 priority_queue 中吗?

    • 可以,priority_queue 支持以 deque 为底层容器,但因为 priority_queue 中通常不需要双端操作,因此更常使用 vector

总结

本文介绍了 C++ 中的 priority_queuedeque 容器,分别适合实现优先级调度和双端队列操作。priority_queuedeque 在实际应用中扮演着重要角色,为各种算法和数据处理提供了高效、简洁的解决方案。希望本篇内容能帮助您更好地理解 C++ 容器的灵活性,并在项目中合理使用这些数据结构。
参考链接:C/C++ Reference

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

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

相关文章

LogViewer NLog, Log4Net, Log4j 文本日志可视化

LogViewer 下载 示例&#xff1a;NLog文本日志可视化软件&#xff0c;并且能够实时监听输出最新的日志 nlog.config 通过udp方式传输给LogViewer (udp://ip:port) <?xml version"1.0" encoding"utf-8" ?> <nlog xmlns"http://www.nlog-…

安卓开发作业

整体效果: 安卓小作业 [TOC](页面配置) 整体框架有4个fragment页面,聊天,朋友,发现,设置. 配置如下: bash <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android" xm…

【QML】QML多线程应用(WorkerScript)

1. 实现功能 QML项目中&#xff0c;点击一个按键后&#xff0c;运行一段比较耗时的程序&#xff0c;此时ui线程会卡住。如何避免ui线程卡住。 2. 单线程&#xff08;会卡住&#xff09; 2.1 界面 2.2 现象 点击delay btn后&#xff0c;执行耗时函数&#xff08;TestJs.func…

深度学习中的Pixel Shuffle和Pixel Unshuffle:图像超分辨率的秘密武器

在深度学习的计算机视觉任务中&#xff0c;提升图像分辨率和压缩特征图是重要需求。Pixel Shuffle和Pixel Unshuffle是在超分辨率、图像生成等任务中常用的操作&#xff0c;能够通过转换空间维度和通道维度来优化图像特征表示。本篇文章将深入介绍这两种操作的原理&#xff0c;…

pom中无法下载下来的类外部引用只给一个jar的时候

比如jar在桌面上放着,操作步骤如下&#xff1a; 选择桌面&#xff0c;输入cmd ,执行mvn install:install-file -DgroupIdcom -DartifactIdaspose-words -Dversion15.8.0 -Dpackagingjar -Dclassifierjdk11 -Dfilejar包名称 即可把jar包引入成功。

群控系统服务端开发模式-应用开发-前端图片格式功能开发

一、添加视图 在根目录下src文件夹下views文件夹下param文件夹下grade文件夹下&#xff0c;新建index.vue&#xff0c;代码如下 <template><div class"app-container"><div class"filter-container" style"float:left;"><…

【Web前端】Promise的使用

Promise是异步编程的核心概念之一。代表一个可能尚未完成的操作&#xff0c;并提供了一种机制来处理该操作最终的成功或失败。具体来说&#xff0c;Promise是由异步函数返回的对象&#xff0c;能够指示该操作当前所处的状态。 当Promise被创建时&#xff0c;它会处于“待定”&a…

EEG+EMG学习系列 (2) :实时 EEG-EMG 人机界面的下肢外骨骼控制系统

[TOC]( EEGEMG学习系列(2):实时 EEG-EMG 人机界面的下肢外骨骼控制系统) 论文地址&#xff1a;https://ieeexplore.ieee.org/abstract/document/9084126 论文题目&#xff1a;Real-Time EEG–EMG Human–Machine Interface-Based Control System for a Lower-Limb Exoskeleton …

Spring Authorization Server OAuth2.1

Spring Authorization Server介绍 Spring Authorization Server 是一个框架&#xff0c;它提供了 OAuth 2.1 和 OpenID Connect 1.0 规范以及其他相关规范的实现。 它建立在 Spring Security 之上&#xff0c;为构建 OpenID Connect 1.0 身份提供者和 OAuth2 授权服务器产品提供…

《生成式 AI》课程 第3講 CODE TASK 任务3:自定义任务的机器人

课程 《生成式 AI》课程 第3講&#xff1a;訓練不了人工智慧嗎&#xff1f;你可以訓練你自己-CSDN博客 我们希望你创建一个定制的服务机器人。 您可以想出任何您希望机器人执行的任务&#xff0c;例如&#xff0c;一个可以解决简单的数学问题的机器人0 一个机器人&#xff0c…

Python知识点精汇!字符串:定义、截取(索引)和其内置函数

目录 一、字符串的定义 二、字符串的截取 1.截取干啥的 2.怎么用截取 3.打印多次 4.两个字符串拼接在一起 三、字符串内置函数 1.查询函数&#xff1a; &#xff08;1&#xff09;find(str,start,end) &#xff08;2&#xff09;index&#xff08;str,start,end&#…

创建vue+electron项目流程

一个vue3和electron最基本的环境搭建步骤如下&#xff1a;// 安装 vite vue3 vite-plugin-vue-setup-extend less normalize.css mitt pinia vue-router npm create vuelatest npm i vite-plugin-vue-setup-extend -D npm i less -D npm i normalize.css -S &#xff0…

从0开始机器学习--Day27--主成分分析方法

主成分分析方法(Principal components analysis) 在降维算法中&#xff0c;比较普遍的是使用主成分分析方法&#xff08;PCA&#xff09; PCA算法简单示例 如图&#xff0c;假设我们有一个二维的特征&#xff0c;想要将其降为一维&#xff0c;简单的方法是寻找一条直线&#…

无效的目标发行版17和无法连接Maven进程问题

起因&#xff1a;我clean了一个模块的Maven想要重新下&#xff0c;他就开始报错。两次了都是这样。如果和我一样一开始都是好好的&#xff0c;直接找Maven的设置&#xff0c;在运行程序改&#xff0c;jre变成了11.它自己变成了我其他的jdk

【Android、IOS、Flutter、鸿蒙、ReactNative 】启动页

Android 设置启动页 自定义 splash.xml 通过themes.xml配置启动页背景图 IOS 设置启动页 LaunchScreen.storyboard 设置为启动页 storyboard页面绘制 Assets.xcassets 目录下导入图片 AppLogo Flutter 设置启动页 Flutter Android 设置启动页 自定义 launch_background.xm…

Java实现多线程编程

目录 一、创建线程 1.1.第一种方法&#xff1a;继承Thread类 1.2.第二种方法&#xff1a;实现Runnable接口 1.3.其他创建线程的方法 二、多线程的优势-增加运行速度 三、Thread类及常见方法 3.1 Thread常见的构造方法 3.2Thread的几个常见方法 3.2.1启动一个线程——sta…

【快速解决】kafka崩了,重启之后,想继续消费,怎么做?

目录 一、怎么寻找我们关心的主题在崩溃之前消费到了哪里&#xff1f; 1、一个问题&#xff1a; 2、查看消费者消费主题__consumer_offsets 3、一个重要前提&#xff1a;消费时要提交offset 二、指定 Offset 消费 假如遇到kafka崩了&#xff0c;你重启kafka之后&#xff0…

【设计模式】行为型模式(四):备忘录模式、中介者模式

《设计模式之行为型模式》系列&#xff0c;共包含以下文章&#xff1a; 行为型模式&#xff08;一&#xff09;&#xff1a;模板方法模式、观察者模式行为型模式&#xff08;二&#xff09;&#xff1a;策略模式、命令模式行为型模式&#xff08;三&#xff09;&#xff1a;责…

GRE做题笔记(零散的个人经验)

locomotive机车By 1813, the Luddite resistance had all but vanished. all but表示“几乎完全”的程度&#xff0c;或者表示排除piston活塞attributed to 归因于how a sportsperson accounted for their own experience of stress 运动员如何解释自己的压力经历 &#xff0c;…

【vmware+ubuntu16.04】vm虚拟机及镜像安装-tools安装包弹不出来问题

学习机器人这门课需要下载虚拟机&#xff0c;做一下记录 首先我下载的是vm虚拟机16&#xff0c; 下载版本可参考该文章课堂上我下载 的镜像是16.04&#xff0c;虚拟机安装教程和镜像添加可参考该博主 按照教程安装成功 安装tools&#xff0c;但是我的弹不出来那个压缩包&…