priority_queue(优先级队列)

news2024/11/16 21:37:57

priority_queue

  • 1. priority_queue的介绍及使用
    • 1.1 priority_queue的介绍
    • 1.2 priority_queue的使用
      • 1.2.1 constructor(构造)
      • 1.2.2 empty
      • 1.2.3 size
      • 1.2.4 top
      • 1.2.5 emplace
      • 1.2.6 push、pop、swap
    • 1.3 数组中第K个大的元素
  • 2.priority_queue的深度剖析及模拟实现

在这里插入图片描述

1. priority_queue的介绍及使用

1.1 priority_queue的介绍

在C++中,priority_queue是一个容器适配器,它提供了常数时间的最大元素查找。它通常实现为堆。堆是一种数据结构,其中最大(或最小)元素始终位于顶部。priority_queue是一个模板类,定义在头文件中。它有三个模板参数:元素类型、容器类型和比较函数类型(可选)。默认情况下,它使用std::vector作为其底层容器

1.2 priority_queue的使用

Member functions:
在这里插入图片描述

1.2.1 constructor(构造)

int main ()
{
  int myints[]= {10,60,50,20};

  priority_queue<int> q1;
  priority_queue<int> q2(myints,myints+4);
  priority_queue<int, vector<int>, greater<int>> q3(myints,myints+4);
  return 0;
}
  • q1为空。
  • q2包含为 定义的四个整数,60(最高)位于其顶部。
  • q3具有相同的四个整数,但由于它使用而不是默认值(即),因此它将 10 作为其顶部元素添加新元素。这个新元素是就地构造的,作为其构造函数的参数传递。

1.2.2 empty

在C++ STL中,empty()函数是一个预定义函数,用于检查集合是否为空。如果集合为空,则返回true(1),如果集合不为空,则返回false(0)。对于空的容器,empty()函数返回true,否则返回false 。

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

int main()
{
	int a[] = { 3,6, 2,8,1 };
	priority_queue<int> q1;
	priority_queue<int> q2(a, a + 5);

	cout << "q1:" << q1.empty() << endl;
	cout << "q2:" << q2.empty() << endl;

	return 0;
}

在这里插入图片描述

1.2.3 size

C++ STL中的size()函数返回的是容器中元素的数量 。
在这里插入图片描述

1.2.4 top

top() 函数是 C++ STL 中 priority_queue 类的一个成员函数,用于返回优先队列中的第一个元素的引用 。在使用 top() 函数时,需要注意优先队列是否为空,否则会出现未定义的行为 。

int main()
{
	int a[] = { 3,6, 2,8,1 };
	priority_queue<int> q1;
	priority_queue<int> q2(a, a + 5);

	cout << "q1:" << q1.top() << endl;//报错
	cout << "q2:" << q2.top() << endl;//8

	return 0;
}

在这里插入图片描述

在这里插入图片描述

1.2.5 emplace

构造和插入元素, 添加新元素。这个新元素是就地构造的,作为其构造函数的参数传递

int main()
{
    priority_queue<string> mypq;

    mypq.emplace("orange");
    mypq.emplace("strawberry");
    mypq.emplace("apple");
    mypq.emplace("pear");

    cout << "mypq contains:";
    while (!mypq.empty())
    {
        cout << ' ' << mypq.top();
        mypq.pop();
    }
    cout << '\n';

    return 0;
}

在这里插入图片描述

1.2.6 push、pop、swap

push() 函数用于将新元素插入到 priority_queue 中,并保持队列的有序性。
priority_queue 中的 pop() 函数用于删除队列中的第一个元素,即最大元素 。
swap() 函数用于交换两个 priority_queue 的元素。

int main()
{
	priority_queue<int> q1;
	q1.push(1);
	q1.push(2);
	q1.push(3);
	priority_queue<int> q2;
	q2.push(4);
	q2.push(5);
	q2.push(6);
	swap(q1, q2);

	cout << "q1: ";
	while (!q1.empty())
	{
		cout << q1.top() << ' ';
		q1.pop();
	}
	cout << endl;

	cout << "q2: ";
	while (!q2.empty())
	{
		cout << q2.top() << ' ';
		q2.pop();
	}
	cout << endl;
	return 0;
}

在这里插入图片描述

1.3 数组中第K个大的元素

在这里插入图片描述

数组中第K个大的元素
第一种方法:对数组nums进行排序,然后找第k大个数。需要注意的是,算法中一般排序的时间复杂度都要比O(N)大,也就计数排序接近O(N)。
在这里插入图片描述

第二种方法:建立一个有N个元素的优先级队列,求第k个大的元素,则将优先级队列中前k-1个元素删除掉,最后队列的top就是所求元素

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

在这里插入图片描述

第三种方法:建立一个有K个元素的优先级队列(小堆),然后遍历nums,大的元素进队列,最后队列的top就是所求元素

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k)
    {
        priority_queue<int, vector<int>, greater<int>> deq(nums.begin(), nums.begin() + k);
        for (size_t i = k; i < nums.size(); ++i)
        {
            if (nums[i] > deq.top())
            {
                deq.pop();
                deq.push(nums[i]);
            }
        }
        return deq.top();
    }
};

在这里插入图片描述

2.priority_queue的深度剖析及模拟实现

priority_queue有三个模板参数:元素类型、容器类型和比较函数类型(可选)。默认情况下,它使用std::vector作为其底层容器 ,而且不需要迭代器,所以实现较为简单。

namespace k
{
	template<class T, class Container = vector<T>>
	class priority_deque
	{
	public:
		size_t size()
		{
			return _con.size();
		}
		void push(const T& x)
		{
			_con.push_back(x);
			adjust_up(_con.size() - 1);
		}
		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			adjust_down(0);
		}
		const T& top()
		{
			return _con[0];
		}
		bool empty()
		{
			return _con.empty();
		}
	protected:
		void adjust_up(size_t child)
		{
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
				if (_con[parent] <  _con[child])
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}
		void adjust_down(size_t parent)
		{
			size_t child = parent * 2 + 1;
			while (child < _con.size())
			{
				if (child + 1 < _con.size() && _con[child] < _con[child + 1])
				{
					++child;
				}
				if (_con[parent] < _con[child])
				{
					swap(_con[child], _con[parent]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}
	private:
		Container _con;
	};
}

如上为priority_queue的实现,其中向上调整(adjust_up)、向下调整(asjust_down)调整的是大堆,是写死的,如过要小堆,则怎么弄?这就是模版的细节之处。只要定义一个比较方式,就可以解决。

namespace k
{
	template<class T>
	struct less
	{
		bool operator()(const T& x, const T& y)
		{
			return x < y;
		}
	};
	template<class T>
	struct greater
	{
		bool operator()(const T& x, const T& y)
		{
			return x > y;
		}
	};
	template<class T, class Container = vector<T>, class Compare = less<T>>
	class priority_deque
	{
	public:
		size_t size()
		{
			return _con.size();
		}
		void push(const T& x)
		{
			_con.push_back(x);
			adjust_up(_con.size() - 1);
		}
		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			adjust_down(0);
		}
		const T& top()
		{
			return _con[0];
		}
		bool empty()
		{
			return _con.empty();
		}
	protected:
		void adjust_up(size_t child)
		{
			Compare com;
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
				if (com(_con[parent], _con[child]))
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}
		void adjust_down(size_t parent)
		{
			size_t child = parent * 2 + 1;
			while (child < _con.size())
			{
				Compare com;
				if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
				{
					++child;
				}
				if (com(_con[parent], _con[child]))
				{
					swap(_con[child], _con[parent]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}
	private:
		Container _con;
	};
}

如上定义两个仿函数,然后模版引入就可以实现。

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

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

相关文章

Makerbase SimpleFOC ESP32例程4 双电机闭环速度测试

Makerbase SimpleFOC ESP32例程4 双电机闭环速度测试 第一部分 硬件介绍 1.1 硬件清单 序号品名数量1ESP32 FOC V1.0 主板12YT2804电机2312V电源适配器14USB 线156pin杜邦线2 注意&#xff1a;YT2804是改装的云台无刷电机,带有AS5600编码器&#xff0c;可实现360连续运转。…

柔性作业车间调度

1柔性车间作业调度 个工件 要在 台机器 上加工。每个工件包含一道或多道工序&#xff0c;工序顺序是预先确定的&#xff0c;每道工序可以在多台不同加工机器上进行加工&#xff0c;工序的加工时间随加工机器的不同而不同。调度目标是为每道工序选择最合适的机器、确定每台机器…

【C语言】语言篇——数组和字符串

C站的小伙伴们&#xff0c;大家好呀&#x1f61d;&#x1f61d;&#xff01;我最近在阅读学习刘汝佳老师的《算法竞赛入门经典》&#xff0c;今天将整理本书的第三章——数组和字符串的一些习题&#xff0c;本章习题较多&#xff0c;下选取部分习题进行练习总结&#xff0c;在这…

200道面试题(附答案)

最近有不少小伙伴跑来咨询&#xff1a; 想找网络安全工作&#xff0c;应该要怎么进行技术面试准备&#xff1f;工作不到 2 年&#xff0c;想跳槽看下机会&#xff0c;有没有相关的面试题呢&#xff1f; 为了更好地帮助大家高薪就业&#xff0c;今天就给大家分享两份网络安全工…

ubuntu20.04 ffmpeg mp4转AES加密的m3u8分片视频

样本视频(时长2分35秒): 大雄兔_百度百科 大雄兔_百度百科不知大家否看过世界上第一部开源电影&#xff1a;Elephants Dream&#xff08;大象之梦&#xff09;。这是一部由主要由开源软件Blender制作的电影短片&#xff0c;证明了用开源软件也能制作出效果媲美大公司的作品。…

1-9 随机算法【手写+Xmind笔记】

文章目录 1 Min-Cut【手写笔记】1.1 问题描述1.2 解决方案1.3 概率证明 2 赠券收集【手写笔记】3 快排期望【手写笔记】4 素数性质【手写笔记】4.1 基本性质4.2 解决方案4.3 群论4.4 费马小定理4.5 Miller Rabin素性测试 5-6 力矩与偏差【手写笔记】5.1 基础不等式5.2 矩生成函…

[图表]pyecharts模块-柱状图

[图表]pyecharts模块-柱状图 先来看代码&#xff1a; from pyecharts.charts import Bar from pyecharts.faker import Faker from pyecharts.globals import ThemeTypec (Bar({"theme": ThemeType.MACARONS}).add_xaxis(Faker.choose()).add_yaxis("商家A&q…

Spring 核心概念之一 IoC

前言 欢迎来到本篇文章&#xff01;通过上一篇什么是 Spring&#xff1f;为什么学它&#xff1f;的学习&#xff0c;我们知道了 Spring 的基本概念&#xff0c;知道什么是 Spring&#xff0c;以及为什么学习 Spring。今天&#xff0c;这篇就来说说 Spring 中的核心概念之一 Io…

day2 -- 数据库的安全管理和维护

brief 访问控制的目的不仅仅是防止用户的恶意企图。数据梦魇更为常见的是无意识错误的结果&#xff0c;如错打MySQL语句&#xff0c;在不合适的数据库中操作或其他一些用户错误。通过保证用户不能执行他们不应该执行的语句&#xff0c;访问控制有助于避免这些情况的发生。管理…

Makerbase SimpleFOC ESP32 例程6 双电机闭环位置力矩互控

Makerbase SimpleFOC ESP32 例程6 双电机闭环位置力矩互控 第一部分 硬件介绍 1.1 硬件清单 序号品名数量1ESP32 FOC V1.0 主板12YT2804电机2312V电源适配器14USB 线156pin杜邦线2 注意&#xff1a;YT2804是改装的云台无刷电机,带有AS5600编码器&#xff0c;可实现360连续运…

Go 字节跳动—从需求到上线全流程

走进后端开发流程 整个课程会带大家先从理论出发&#xff0c;思考为什么有流程 大家以后工作的团队可能不一样&#xff0c;那么不同的团队也会有不同的流程&#xff0c;这背后的逻辑是什么 然后会带大家按照走一遍从需求到上线的全流程&#xff0c;告诉大家在流程的每个阶段&am…

angular环境安装 (含nodejs详细安装步骤)

在安装本次环境之前&#xff0c;需要先把本机上的nodejs环境卸载&#xff0c;环境变量手动删除&#xff01;安装过程种环境才不会产生副作用&#xff01;实际项目安装的一次记录&#xff0c;踩了太多坑&#xff0c;记录一下&#xff0c;旨在记录&#xff01;项目需要两个不用版…

常用设计模式介绍~~~ Java实现 【概念+案例+代码】

前言 想要读懂源码、让自己的代码写的更加优雅&#xff0c;重构系统等。理解设计模式的思想&#xff0c;可以让我们事半功倍。以下稍微整理了常用的设计模式、每一种设计模式都有详细的概念介绍、案例说明、代码实例、运行截图等。这里给出目录导航。 目录 一、创建型模式 【一…

现在的面试把我卷崩溃了....

现在的面试也太卷了&#xff0c;前几天组了一个软件测试面试的群&#xff0c;没想到效果直接拉满&#xff0c;看来大家对面试这块的需求还是挺迫切的。昨天我就看到群友们发的一些面经&#xff0c;感觉非常有参考价值&#xff0c;于是我就问他还有没有。 结果他给我整理了一份…

Linux命令学习之cd

cd是进入某个目录的命令。man 1 cd看一下cd的使用说明。 发现cd是一个Shell内置命令。内置命令可以使用help 命令行来看一下帮助&#xff0c;比如help cd就可以看一下cd的帮助。 图中的[dir]就是参数&#xff0c;这个参数是目录名&#xff0c;比如可以使用cd /可以进入根目录…

外包派遣3年华为,合同结束转正,转正后工资12k-15k,13薪,包三餐,值得去吗?

“但凡有点机会&#xff0c;千万别去外包! ” 在程序员圈子里面&#xff0c;外包程序员似乎永远处于一个尴尬的角色&#xff0c;如果你说他们不是程序员吧&#xff0c;他们也是程序员。应该说是外包这个词比较尴尬吧。赶着和正式工一样的伙&#xff0c;待遇缺天差地别&#xf…

使用VS2019如何创建Win32的项目?

闲来无事&#xff0c;想学习一下Win32的开发&#xff0c;使用VS2019如何创建Win32的项目&#xff1f;费了老大的劲儿&#xff0c;终于捣鼓出来&#xff0c;现在记录一下。 1 创建新项目&#xff0c;在筛选栏选择C Windows 桌面&#xff0c;如下图&#xff0c;选择第一个“Windo…

由于找不到msvcr90.dll无法继续执行代码的5个修复方法

msvcr90.dll是Microsoft Visual C 2008 Redistributable软件包中的一个库文件&#xff0c;它是用于在Windows操作系统上运行C应用程序的重要文件之一。当我们电脑系统中的msvcr90.dll丢失或者损坏了&#xff0c;就会导致很多软件跟游戏无法打开运行&#xff0c;会提示“由于找不…

Linux文件权限及用户管理

文件权限 在Linux中&#xff0c;每个文件和目录都有一组权限&#xff0c;这些权限决定了哪些用户可以访问文件或目录&#xff0c;以及他们可以进行什么样的操作。权限分为三类&#xff1a; 所有者权限&#xff1a;这些权限适用于文件或目录的所有者。 组权限&#xff1a;这些…

vue+elementui+nodejs毕业设计选题管理系统x7xs6

为了实现对不同角色的分权限管理&#xff0c;从而让各个用户各司其职。学生用户需要登录系统后才能够进行毕设相关文件上传与查看&#xff0c;教师用户需要登录后才能够在线查看毕设相关文件并审核留言等。管理人员需要登录才能够管理各种功能&#xff0c;这三种用户的权限如下…