C++:优先队列-Priority_queue

发布时间:2024年01月24日

目录

1.关于优先队列

2.priority_queue的使用

1.构造方法

2.empty();判空

3.size();

4.top();

5.push(val);

6.pop();

3.优先队列模拟实现

?4.用优先队列解决数组中第K个大的元素


1.关于优先队列

????????在C++中,可以使用STL(标准模板库)中的priority_queue类来实现优先队列。priority_queue是一个模板类,可以存储任意类型的元素,并按照元素的优先级进行排序。

1.?优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。

2.类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元

)
3. 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类, queue 提供一组特 定的成员函数来访问其元素。元素从特定容器的 尾部 弹出,其称为优先队列的顶部。
4. 底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭 代器访问,并支持以下操作:
empty() :检测容器是否为空
size() :返回容器中有效元素个数
front() :返回容器中第一个元素的引用
push_back() :在容器尾部插入元素
pop_back() :删除容器尾部元素
5.标准容器类 vector deque 满足这些需求。默认情况下,如果没有为特定的 priority_queue 类实例化指定容器类,则使用vector
6. 需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器通过在需要时自动调用算法函数 make_heap push_heap pop_heap 来自动完成此操作。

2.priority_queue的使用

????????优先级队列默认使用vector 作为其底层存储数据的容器,在 vector 上又使用了堆算法将 vector 中元素构造成 堆的结构,因此 priority_queue 就是堆,所有需要用到堆的位置,都可以考虑使用 priority_queue
注意: 默认情况下 priority_queue 是大堆
如果要小堆,将第三个模板参数换成greater比较方式
#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<queue>

using namespace std;

int main()
{
	 vector<int>nums = { 1,2,4,6,78,4,23,65,3,12,5,45 };
	priority_queue<int, vector<int>, greater<int>> p(nums.begin(), nums.end());
	while (!p.empty())
	{
		cout << p.top() << " ";
		p.pop();
	}
	return 0;
}

?

1.构造方法

1.priority queue();

构造一个空的优先级队列

comp用于对堆进行排序的比较对象。这可能是一个函数指针或函数对象,能够通过比较其两个参数来执行严格的弱排序。
Compare 是第三类模板参数(默认为:less<T>)。默认为大根堆。

ctnr容器对象。
容器是第二个类模板参数(priority_queue的基础容器的类型;默认为:vector<T>)。

2.priority queue(first,last);

将迭代器输入到序列中的初始和最终位置。在对基础容器进行排序之前,将此序列中的元素插入到基础容器中。
使用的范围是 [first,last),它包括 first 和 last 之间的所有元素,包括 first 指向的元素,但不包括 last 指向的元素。

2.empty();判空

返回priority_queue是否为空:即其大小是否为零。

此成员函数有效地调用基础容器对象的空成员。

3.size();

返回priority_queue中的元素数。

此成员函数有效地调用基础容器对象的成员大小。

4.top();

返回对 priority_queue 中顶部元素的常量引用。

top 元素是priority_queue中比较较高的元素,以及调用 priority_queue::p op 时从容器中删除的下一个元素。此成员函数有效地调用基础容器对象的成员前端。

5.push(val);

在priority_queue中插入一个新元素。此新元素的内容初始化为 val。

此成员函数有效地调用基础容器对象的成员函数push_back,然后通过对包含容器的所有元素的范围调用 push_heap 算法,将其重新排序到堆中的位置。

6.pop();

移除priority_queue顶部的元素,有效地将其尺寸减小 1。删除的元素是具有最高值的元素。

在弹出之前,可以通过调用成员 priority_queue::top 来检索此元素的值。此成员函数有效地调用 pop_heap 算法来保留 priority_queues 的堆属性,然后调用基础容器对象的成员函数pop_back来删除元素。这将调用已删除元素的析构函数。

3.优先队列模拟实现

在vector容器基础上利用堆的向上调整算法和向下调整算法来实现。插入删除时保持堆属性。

#pragma once

namespace wjc
{
	template<class T>
	struct less
	{
		bool operator()(const T& left, const T& right)
		{
			return left < right;
		}
	};
	template<class T>
	struct greater
	{
		bool operator()(const T& left, const T& right)
		{
			return left > right;
		}
	};
	template<class T,class Container=vector<T>,class Compare=less<T>>
	class priority_queue
	{
	public:
		priority_queue()
			:_con()
		{
		};
		template<class Iterator>
		priority_queue(Iterator first, Iterator last)
			:_con(first, last)
		{
			int count = _con.size();
			int root = ((count - 1 - 1) / 2);
			while (root >= 0)
			{
				AdjustDown(root);
				root--;
			}
		}


		void push(const T& data)
		{
			_con.pushback(data);
			AdjustUp(_con.size() - 1);
		}

		void pop()
		{
			if (empty())
				return;
			swap(_con.front(), _con.back());
			_con.pop_back();
			AdjustDown(0);
		}

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

		size_t size()const
		{
			return _con.size();
		}

		const T& top()const
		{
			return _con.front();
		}

		void AdjustDown(int parent)
		{
			int child = parent * 2 + 1;
			while (child < _con.size())
			{
				if (child + 1 < _con.size() && Compare()(_con[child], _con[child + 1]))
					child++;
				if (Compare()(_con[parent], _con[child]))
				{
					swap(_con[parent], _con[child]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
					break;
			}

		}

		void AdjustUp(int child)
		{
			int parent = (child - 1) / 2;
			while (child >= 0)
			{
				if (Compare()(_con[parent], _con[child]))
				{
					swap(_con[parent], _con[child]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
					break;
			}
		}

	private:
		Container _con;
	};




}

测试代码

//如果需要升序排序 ?利用不同比较方法建小堆

#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<vector>
#include"priority_queue.h"

int main()
{
	vector<int> v = { 2,3,6,3,2,45,74,23,21 };
	//wjc::priority_queue<int> p(v.begin(), v.end());     //默认大堆
	//如果需要升序排序  利用不同比较方法建小堆
	wjc::priority_queue<int,vector<int>,greater<int>> p(v.begin(), v.end());
	while (!p.empty())
	{
		cout << p.top() << " ";
		p.pop();
	}
	return 0;
}

?

?4.用优先队列解决数组中第K个大的元素

给定整数数组?nums?和整数?k,请返回数组中第?k?个最大的元素。

请注意,你需要找的是数组排序后的第?k?个最大的元素,而不是第?k?个不同的元素。

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

因为优先队列默认是大堆,所以删除--k个元素,堆顶就是第K大个元素,也就是p.top();

文章来源:https://blog.csdn.net/decade777555/article/details/135796159
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。