【C++】STL优先级队列(priority_queue)

news2024/11/15 14:03:22

在这里插入图片描述

priority_queue 基本介绍

priority_queue就是优先级队列。其头文件就是queue,但是队列和优先级队列关系不大,两个是不同的数据结构。但二者都是适配器,容器适配器。

在这里插入图片描述

优先级队列中存放的数据是有优先级的。

其内部有以下成员方法,其中常用的就empty, size, top, push, pop。

在这里插入图片描述

直接演示一下常用方法的使用:

我们看到用法几乎是与栈和队列一样。但是这里打印结果是排好序了(降序)。所以,优先级队列默认情况下是大的优先。

优先级队列的适配器

在这里插入图片描述

看其第二个模板参数:class Container = vector,这就是容器适配器。因此我们可以将其底层的容器改为其他的容器(list不行):

在这里插入图片描述

第三个模板参数compare

在这里插入图片描述

跟sort用法很像,sort第三个参数传的是一个对象,比如说给sort传greater()就是降序,而这里传的是类型,比如说传greater就是小堆。可以看到,模板参数缺省值为less,可能有的同学不知道value_type是啥,其实就是我们日常放在容器中的元素类型,就是那个T,T可以为int、char什么的都行。所以我们默认情况下参数 Compare 就是less的类型,那么就是大堆。

在这里插入图片描述

这样就变成了小堆,每次取堆顶的值就是最小值。

  • 传greater时是小堆。
  • 传less时是大堆。

使用优先级队列来解决这个问题:数组中第K个最大的元素

在这里插入图片描述

题目中有要求,必须设计时间复杂度为O(N)的算法。那么先进行排序操作的同学就另寻他路吧。这道题就可以用到优先级队列,就是堆。先把堆建好,然后pop k-1次后的堆顶就是第k大的元素。

class Solution 
{
public:
    int findKthLargest(vector<int>& nums, int k) 
    {
        priority_queue<int> pq(nums.begin(), nums.end());
        while(--k)
        {
             pq.pop();
        }
        return pq.top();
    }
};

priority_queue 的模拟实现

堆的实现的核心无非就是向上调整和向下调整。而堆虽然逻辑结构上是二叉树,但是实际物理结构就是数组。我们用C++写,默认容器就是vector,因为随机访问数据的次数比较多。我们很多地方就可以直接复用vector中的函数接口,所以就需要自己动手写两个,一个是向上调整,一个是向下调整。

#include<vector>
#include<algorithm>
#include<iostream>

namespace Flash
{
	template<class T, class Container = std::vector<T>,class Compare = less<T>>
	class priority_queue
	{
	private:
		//向上调整
		void adjust_up(size_t child)
		{
			Compare com;
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
				//if (_con[child] > _con[parent])
				//if (_con[parent] < _con[child])
				if (com(_con[parent], _con[child]))
				{
					std::swap(_con[child], _con[parent]);
				}
				else
				{
					break;
				}
				child = parent;
				parent = (child - 1) / 2;
			}
		}
		//向下调整
		void adjust_down(size_t parent)
		{
			Compare com;
			size_t child = parent * 2 + 1;
			while (child < _con.size())
			{
				if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
				{
					++child;
				}
				//if (_con[parent] < _con[child])
				if (com(_con[parent], _con[child]))
				{
					std::swap(_con[child], _con[parent]);
				}

				else
				{
					break;
				}
				parent = child;
				child = parent * 2 + 1;
			}
		}
	public:
		void push(const T& x)
		{
			_con.push_back(x);
			adjust_up(_con.size() - 1);
		}

		void pop()
		{
			std::swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			adjust_down(0);
		}

		const T& top()
		{
			return _con[0];
		}

		bool empty()const
		{
			return _con.empty();
		}

		int size()const
		{
			return _con.size();
		}
	private:
		Container _con;
	};

	template<class T>
	struct less
	{
		bool operator()(const T& L, const T& R)
		{
			return L < R;
		}
	};

	template<class T>
	struct greater
	{
		bool operator()(const T& L, const T& R)
		{
			return L > R;
		}
	};

}

上面基本功能的是实现了,但是问题是不能控制大小堆,那我们可以像库中那样,再搞一个模板参数,传一个仿函数来实现大小堆的控制。

仿函数

仿函数就是一个类,里面重载了()运算符。

在这里插入图片描述在这里插入图片描述

第一个ls(1, 2)乍一看就像是函数调用,但实际上就是类匿名对象调用了operator()。

在这里插入图片描述

再来个greater:

在这里插入图片描述
在这里插入图片描述

这就是仿函数,用类来重载()来实现。调用的时候就像函数一样,在C语言阶段学过的qsort,传比较的那个参数的时候要传函数指针,但是函数指针太麻烦了,所以C++为了不再用函数指针,就搞了仿函数。

那么此时我们就可以搞第三个模板参数了。

在这里插入图片描述

传的是类型。然后把我们向上调整和向下调整中的代码改一改:

在这里插入图片描述
在这里插入图片描述

上面的priority_queue、less、greater都是在一个命名空间FangZhang中的,所以除了vector是复用的,剩下的都是手写的,less和greater就是刚写出来的那两个,可以直接用。

在这里插入图片描述

再来强调一点:

假如说一个对象vector v,我们用sort时,传参是sort(v.begin(), v.end(), less()),而这堆这是定义对象传模板参数priority_queue<int, vector, less>,前者是传匿名对象,后者是传类型。是不一样的。不要搞混。

栈和队列还有优先级队列都是容器适配器,就是可以改变其底层所使用的容器,从而能够用不同的容器来实现其底层的函数接口。

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

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

相关文章

跟着cherno手搓游戏引擎【17】整理代码、timestep和transform

这里就不分部走了&#xff0c;直接上代码。 全局&#xff1a; YOTO.h:添加renderer的头文件&#xff1a; #pragma once//用于YOTO APP#include "YOTO/Application.h" #include"YOTO/Layer.h" #include "YOTO/Log.h"#include"YOTO/Core/T…

V2X,启动高增长引擎

车载通讯的下一个新周期&#xff0c;毋庸置疑是V2X。从4G、5G再到C-V2X&#xff0c;是车载通讯逐步从信息娱乐、行车数据监控到万物互联的关键。 去年5月&#xff0c;全球车载通讯芯片巨头—高通公司宣布&#xff0c;与以色列车联网&#xff08;V2X&#xff09;芯片设计公司Aut…

DevOps落地笔记-05|非功能需求:如何有效关注非功能需求

上一讲主要介绍了看板方法以及如何使用看板方法来解决软件研发过程中出现的团队过载、工作不均、任务延期等问题。通过学习前面几个课时介绍的知识&#xff0c;你的团队开始源源不断地交付用户价值。用户对交付的功能非常满意&#xff0c;但等到系统上线后经常出现服务不可用的…

扣库的函数经验

有的库确实可以提出来的 比如这个库 GitHub - intel/x86-simd-sort: C template library for high performance SIMD based sorting algorithms 根据自己的需要是可以&#xff0c;把内容抠出来的&#xff0c;重新build的。 我就自己新建了一个vs的工程&#xff0c;然后把源…

将java对象转换为json字符串的几种常用方法

目录 1.关于json 2.实现方式 1.Gson 2.jackson 3.fastjson 3.与前端的联系 1.关于json JSON是一种轻量级的数据交换格式。它由Douglas Crockford在2001年创造。JSON的全称是JavaScript Object Notation&#xff0c;它是一种文本格式&#xff0c;可以轻松地在各种平台之间传…

【GEE】基于GEE可视化和下载Landsat8 L2A数据(镶嵌、裁剪)

之前发过一篇使用GEE下载Landsat8的文章&#xff0c;然后有很多小伙伴私信我各种问题&#xff0c;如L1C、L2数据代码怎么修改&#xff0c;如何镶嵌&#xff0c;如何去云、 如何裁剪等一系列问题。正好快过年了&#xff0c;手头的事也没有多少了&#xff0c;所以这两天整理了一下…

考研高数(数列极限之f(xn)和{xn}的关系)

说白了&#xff0c;f(xn)是复合函数&#xff0c;是f(x)与{xn}的复合函数。&#xff08;复合函数的单调性有同增异减的原则&#xff09; 例题1&#xff1a;【可以用同增异减的原则&#xff0c;迅速解答&#xff08;有不合理的地方&#xff0c;请各位大佬指正&#xff01;&#…

【操作系统】FileOutputStream的flush操作有时不生效

按照我们的理解&#xff1a;FileOutputStream的flush()方法的作用就是将缓冲区中的数据立即写入到文件中&#xff0c;即使缓冲区没有填满。这样可以确保数据的及时写入&#xff0c;而不需要等待缓冲区填满或者调用 close() 方法关闭流时才写入。真的是这样吗&#xff1f;&#…

dv和ov通配符SSL证书的区别

SSL数字证书是一种数字证书&#xff0c;可以保护网站传输数据安全以及对服务器身份进行验证&#xff0c;SSL证书有很多种&#xff0c;而通配符证书则是其中的一种特殊类型。SSL证书旗下的通配符SSL证书随着互联网的发展&#xff0c;颁发量也越来越多&#xff0c;为了使用户选择…

websocket编写聊天室

【黑马程序员】WebSocket打造在线聊天室【配套资料源码】 总时长 02:45:00 共6P 此文章包含第1p-第p6的内容 简介 温馨提示&#xff1a;现在都是第三方支持聊天&#xff0c;如极光&#xff0c;学这个用于自己项目完全没问题&#xff0c;大项目不建议使用 需求分析 代码

Celeryconfig配置文件

Celery配置文件 本篇介绍Celery配置文件相关&#xff0c;celeryconfig.py Celeryconfig.py 在上篇celery基础用法中&#xff0c;是这样使用celery的实例化的。 # tasks.py 文件名需与实例化对象第一个参数一致 import time from celery import Celeryredis_url redis://Pa…

重磅!讯飞星火V3.5正式发布,3大核心能力超GPT-4 Turbo!

1月30日&#xff0c;科大讯飞召开星火认知大模型V3.5升级发布会&#xff0c;这是国内首个基于全国产算力训练的多模态认知大模型。科大讯飞董事长刘庆峰先生、研究院院长刘聪先生出席了大会&#xff0c;并对最新产品进行了多维度解读。 讯飞星火V3.5的7大核心能力实现全面大幅…

用的到的linux-文件移动-Day2

前言&#xff1a; 在上一节&#xff0c;我们复习了cd大法和创建生成文件和文件夹的方法&#xff0c;介绍了一些“偷懒”&#xff08;高效&#xff09;的小技巧&#xff0c;本节&#xff0c;我们一起来探讨下&#xff0c;我们对文件移动操作时有哪些可以偷懒的小技巧~ 一、复制…

Oracle 集群】RAC知识图文详细教程(四)--缓存融合技术和主要后台进程

Cache Fusion 原理 前面已经介绍了 RAC 的后台进程&#xff0c;为了更深入的了解这些后台进程的工作原理&#xff0c;先了解一下 RAC 中多节点对共享数据文件访问的管理是如何进行的。要了解 RAC 工作原理的中心&#xff0c;需要知道 Cache Fusion 这个重要的概念&#xff0c;要…

基于腾讯云服务器搭建幻兽帕鲁服务器保姆级教程

随着网络游戏的普及&#xff0c;越来越多的玩家希望能够拥有自己的游戏服务器&#xff0c;以便能够自由地玩耍。而腾讯云服务器作为一个优秀的云计算平台&#xff0c;为玩家们提供了一个便捷、稳定、安全的游戏服务器解决方案。本文将为大家介绍如何基于腾讯云服务器搭建幻兽帕…

三、C++中的Mat对象

图片在C中是作为矩阵Matrix进行处理对待的&#xff0c;通过Mat数据类型进行处理 新建项目这里就不再赘述了哈&#xff0c;可以参考博文&#xff1a;零、环境搭建(第三部分Visula Studio中新建项目) 我这边创建的项目名称为&#xff1a;1_31_matrix 为了养成良好的项目开发习惯…

ubuntu QT openssl支持https

1、Building Qt 5 from Git - Qt Wiki 2、下载编译对应的opengssl [ 1.1.1 ] - /source/old/1.1.1/index.html 3、安装所需基础工具 sudo apt-get install build-essential perl python3 git sudo apt-get install ^libxcb.*-dev libx11-xcb-dev libglu1-mesa-dev libxrende…

基于YOLOv8的水下生物检测,多种优化方法---MSAM(CBAM升级版)助力涨点(二)

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文主要内容:详细介绍了水下生物检测整个过程&#xff0c;从数据集到训练模型到结果可视化分析&#xff0c;以及如何优化提升检测性能。 &#x1f4a1;&#x1f4a1;&#x1f4a1;加入自研注意力MSAM mAP0.5由原始的0.522提升至0.534…

Epicypher—SMARCA2 Chromatin Remodeling Enzyme (Human BRM)

EpiCypher是一家为表观遗传学和染色质生物学研究提供高质量试剂和工具的专业制造商。EpiCypher&#xff08;国内授权代理 欣博盛生物&#xff09;能提供全长重组人SMARCA2重塑酶。SMARCA2是ATP依赖性染色质重塑复合物SWI/SNF的核心ATP酶亚基&#xff0c;可动员核小体&#xff0…

第二百九十九回

文章目录 1. 概念介绍2. 实现方法2.1 使用Steam实现2.2 使用Timer实现 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何实现每隔一段时间执行某项目任务"相关的内容&#xff0c;本章回中将介绍如何实现倒计时功能.闲话休提&#xff0c;让我们一起Talk Flutter吧…