【C++/STL】:优先级队列的使用及底层剖析&&仿函数

💡前言

优先队列(priority_queue)是一种容器适配器,默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。注意:默认情况下priority_queue是大堆

注意:使用优先级队列要包含头文件 < queue >

一,优先级队列的使用

在这里插入图片描述

代码实现如下:

这里的建堆一般有两种方式:
(1) 一种是一个一个push进vector容器再进行向上调整建堆
(2) 另一种是直接用迭代器区间构造直接建堆(推荐用这种)

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

void test_priority_queue()
{
	vector<int> v = { 6,0,3,5,4,7,9,1,2,8 };

	//默认升序
	//priority_queue<int> pq(v.begin(), v.end());

	//一个一个尾插建堆
	priority_queue<int, vector<int>, greater<int>> pq;
	for (auto e : v)
	{
		pq.push(e);
	}

	//迭代器区间构造,直接建堆
	//priority_queue<int,vector<int>,greater<int>> pq(v.begin(), v.end());

	while (!pq.empty())
	{
		cout << pq.top() << " ";
		pq.pop();
	}
	cout << endl;

}

int main()
{
	test_priority_queue();

	return 0;
}

注意:优先级队列默认的大堆,降序排列,如果要升序,就要换仿函数。下图中第三个模板参数就是传仿函数。

使用算法库里的 less 和 greater 算法,需要包含头文件< functional >

在这里插入图片描述

二,仿函数

1,什么是仿函数

仿函数也叫函数对象,是一个重载了 operator() 的类,可以使得类的对象像函数一样使用

2,仿函数的简单示例

operator()并没有参数的个数和返回值,所以使用是十分灵活的

struct Func1
{
	//无参无返回值
	void operator()()
	{
		cout << "Func调用" << endl;
	}
};

struct Func2
{
	//有参无返回值
	void operator()(int n)
	{
		while (n--)
		{
			cout << "Func调用" << endl;
		}
	}
};

int main()
{
	Func1 f1;
	f1();  //使得对象像函数一样使用
	f1.operator()(); //显示调用

	cout << endl;

	Func2 f2;
	f2(3);  //使得对象像函数一样使用

	return 0;
}

在这里插入图片描述

三,优先级队列的底层剖析

namespace ling
{
	template<class T>
	class myless
	{
	public:
	    bool operator()(const T& x, const T& y)
	    {
	        return x < y;
	    }
	};
	
	template<class T>
	class mygreater
	{
	public:
	    bool operator()(const T& x, const T& y)
	    {
	        return x > y;
	    }
	};
	
	template <class T, class Container = vector<T>, class Compare = myless<T>>
	class priority_queue
	{
	public:
	    priority_queue() = default;
		
		//迭代器区间构造
	    template <class InputIterator>
	    priority_queue(InputIterator first, InputIterator last)
	    {
	        while (first != last)
	        {
	            con.push_back(*first);
	            ++first;
	        }
	        //建堆
	        for (int i = (con.size() - 1 - 1) / 2; i >= 0; i--)
	        {
	            Adjust_down(i);
	        }
	    }
	
	    bool empty() const
	    {
	        return con.empty();
	    }
	
	    size_t size() const
	    {
	        return con.size();
	    }
		
		// 堆顶元素不允许修改,因为:堆顶元素修改可以会破坏堆的特性
	    const T& top()const
	    {
	        return con[0];
	    }
	
	    //向上调整
	    void Adjust_up(int child)
	    {
	        int parent = (child - 1) / 2;
	        while (child > 0)
	        {
	            //if (con[parent] < con[child])
	            if(comp(con[parent], con[child]))
	            {
	                swap(con[parent], con[child]);
	                child = parent;
	                parent = (child - 1) / 2;
	            }
	            else
	            {
	                break;
	            }
	        }
	    }
	
	    void push(const T& x)
	    {
	        con.push_back(x);
	        Adjust_up(con.size() - 1);
	    }
	
	    //向下调整
	    void Adjust_down(int parent)
	    {
	        int child = parent * 2 + 1;
	        while (child < con.size())
	        {
	            if (child + 1 < con.size() && comp(con[child], con[child + 1]))
	            {
	                child += 1;
	            }
	            //if (con[parent] < con[child])
	            if(comp(con[parent], con[child]))
	            {
	                swap(con[parent], con[child]);
	                parent = child;
	                child = parent * 2 + 1;
	            }
	            else
	            {
	                break;
	            }
	        }
	    }
	
	    void pop()
	    {
	        swap(con[0], con[con.size() - 1]);
	        con.pop_back();
	
	        Adjust_down(0);
	    }
	private:
	    Container con;
	    Compare comp;
	};
}

测试代码

void TestQueuePriority()
{
	ling::priority_queue<int> q1;
	q1.push(5);
	q1.push(1);
	q1.push(4);
	q1.push(2);
	q1.push(3);
	q1.push(6);
	cout << q1.top() << endl;

	q1.pop();
	q1.pop();
	cout << q1.top() << endl;

	vector<int> v{ 5,1,4,2,3,6 };
	ling::priority_queue<int, vector<int>, ling::greater<int>> q2(v.begin(), v.end());
	cout << q2.top() << endl;

	q2.pop();
	q2.pop();
	cout << q2.top() << endl;
}
  • 67
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 61
    评论
评论 61
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值