priority_queue
在<queue>頭文件中,還定義了另一個非常有用的模板類priority_queue(優先隊列)。優先隊列與隊列的差別在於優先隊列不是按照入隊的順序出隊,而是按照隊列中元素的優先權順序出隊(默認爲大者優先,也可以通過指定算子來指定自己的優先順序)。
priority_queue模板類有三個模板參數,第一個是元素類型,第二個容器類型,第三個是比較算子。其中後兩個都可以省略,默認容器爲vector,默認算子爲less,即小的往前排,大的往後排(出隊時序列尾的元素出隊)。
定義priority_queue對象的示例代碼如下:
priority_queue<int> q1;
priority_queue< pair<int, int> > q2; // 注意在兩個尖括號之間一定要留空格。
priority_queue<int, vector<int>, greater<int> > q3; // 定義小的先出隊
priority_queue的基本操作與queue相同。
初學者在使用priority_queue時,最困難的可能就是如何定義比較算子了。
如果是基本數據類型,或已定義了比較運算符的類,可以直接用STL的less算子和greater算子——默認爲使用less算子(大根堆),即小的往前排(二叉樹是作爲兒子往下排),大的先出隊(位於頂端)。注意:除了頂端最大(或最小)以外,其它的不一定有序!
如果要定義自己的比較算子,方法有多種,這裏介紹其中的一種:重載比較運算符。優先隊列試圖將兩個元素x和y代入比較運算符(對less算子,調用 x<y,對greater算子,調用x>y),若結果爲真,則x排在y前面,y將先於x出隊,反之,則將y排在x前面,x將先出隊。
priority_queue 調用 STL裏面的 make_heap(), pop_heap(), push_heap() 算法
實現,也算是堆的另外一種形式。
先寫一個用 STL 裏面堆算法實現的與真正的STL裏面的 priority_queue 用法相
似的 priority_queue, 以加深對 priority_queue 的理解
- #include <iostream>
- #include <algorithm>
- #include <vector>
- using namespace std;
- class priority_queue
- {
- private:
- vector<int> data;
- public:
- void push( int t ){
- data.push_back(t);
- push_heap( data.begin(), data.end());
- }
- void pop(){
- pop_heap( data.begin(), data.end() );
- data.pop_back();
- }
- int top() { return data.front(); }
- int size() { return data.size(); }
- bool empty() { return data.empty(); }
- };
- int main()
- {
- priority_queue test;
- test.push( 3 );
- test.push( 5 );
- test.push( 2 );
- test.push( 4 );
- while( !test.empty() ){
- cout << test.top() << endl;
- test.pop(); }
- return 0;
- }
STL裏面的 priority_queue 寫法與此相似,只是增加了模板及相關的迭代器什麼的。
priority_queue 對於基本類型的使用方法相對簡單。
他的模板聲明帶有三個參數,priority_queue<Type, Container, Functional>
Type 爲數據類型, Container 爲保存數據的容器,Functional 爲元素比較方式。
Container 必須是用數組實現的容器,比如 vector, deque 但不能用 list.
STL裏面默認用的是 vector. 比較方式默認用 operator< , 所以如果你把後面倆個
參數缺省的話,優先隊列就是大頂堆,隊頭元素最大。
看例子
- #include <iostream>
- #include <queue>
- using namespace std;
- int main(){
- priority_queue<int> q;
- for( int i= 0; i< 10; ++i ) q.push( rand() );
- while( !q.empty() ){
- cout << q.top() << endl;
- q.pop();
- }
- getchar();
- return 0;
- }
STL裏面定義了一個仿函數 greater<>,對於基本類型可以用這個仿函數聲明小頂堆
例子:
- #include <iostream>
- #include <queue>
- using namespace std;
- int main(){
- priority_queue<int, vector<int>, greater<int> > q;
- for( int i= 0; i< 10; ++i ) q.push( rand() );
- while( !q.empty() ){
- cout << q.top() << endl;
- q.pop();
- }
- getchar();
- return 0;
- }
先看看例子:
- #include <iostream>
- #include <queue>
- using namespace std;
- struct Node{
- int x, y;
- Node( int a= 0, int b= 0 ):
- x(a), y(b) {}
- };
- bool operator<( Node a, Node b ){
- if( a.x== b.x ) return a.y> b.y;
- return a.x> b.x;
- }
- int main(){
- priority_queue<Node> q;
- for( int i= 0; i< 10; ++i )
- q.push( Node( rand(), rand() ) );
- while( !q.empty() ){
- cout << q.top().x << ' ' << q.top().y << endl;
- q.pop();
- }
- getchar();
- return 0;
- }
自定義類型重載 operator< 後,聲明對象時就可以只帶一個模板參數。
但此時不能像基本類型這樣聲明
priority_queue<Node, vector<Node>, greater<Node> >;
原因是 greater<Node> 沒有定義,如果想用這種方法定義
則可以按如下方式
例子:
- #include <iostream>
- #include <queue>
- using namespace std;
- struct Node{
- int x, y;
- Node( int a= 0, int b= 0 ):
- x(a), y(b) {}
- };
- struct cmp{
- bool operator() ( Node a, Node b ){
- if( a.x== b.x ) return a.y> b.y;
- return a.x> b.x; }
- };
- int main(){
- priority_queue<Node, vector<Node>, cmp> q;
- for( int i= 0; i< 10; ++i )
- q.push( Node( rand(), rand() ) );
- while( !q.empty() ){
- cout << q.top().x << ' ' << q.top().y << endl;
- q.pop();
- }
- getchar();
- return 0;
- }