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

avatar
作者
猴君
阅读量:0

目录

💡前言

优先队列(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; } 

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!