【C++-STL 隊列與優先隊列用法詳解】html
一、隊列queueios
queue 模板類的定義在<queue>頭文件中。
與stack 模板類很類似,queue 模板類也須要兩個模板參數,一個是元素類型,一個容器類
型,元素類型是必要的,容器類型是可選的,默認爲deque 類型。
定義queue 對象的示例代碼以下:
queue<int> q1;
queue<double> q2;
queue 的基本操做有:
入隊,如例:q.push(x); 將x 接到隊列的末端。
出隊,如例:q.pop(); 彈出隊列的第一個元素,注意,並不會返回被彈出元素的值。
訪問隊首元素,如例:q.front(),即最先被壓入隊列的元素。
訪問隊尾元素,如例:q.back(),即最後被壓入隊列的元素。
判斷隊列空,如例:q.empty(),當隊列空時,返回true。
訪問隊列中的元素個數,如例:q.size()算法
【示例代碼1】less
#include <iostream> #include <queue> using namespace std; int main() { int e,m; int len; queue<int> q; for(int i=0;i<10;i++){ q.push(i);//入隊操做,q.push(x); 將x接到隊列的末端 } if(!q.empty()){//q.empty(),當隊列空時,返回true cout<<"隊列非空"<<endl; } len=q.size(); cout<<"隊列長度爲:"<<len<<endl; e=q.front();//q.front(),即最先被壓入隊列的元素 m=q.back();//q.back(),即最後被壓入隊列的元素 cout<<e<<" "<<m<<endl; q.pop();//出隊操做,q.pop(); 彈出隊列的第一個元素,注意,並不會返回被彈出元素的值 e=q.front(); cout<<e<<endl; for(int j=0;j<len-1;j++)//循環出隊 { e=q.front(); cout<<e<<" "; q.pop(); } cout<<endl; return 0; }
2、優先隊列函數
priority_queue<int> p;測試
【經常使用函數】 大數據
(1)priority_queue::empty
判斷隊列是否爲空(也便是size是否爲0),是則返回true,不然返回false。優先隊列的此成員函數實際上調用底層容器的同名函數。
(2)priority_queue::size
返回隊列中元素的個數。此函數實際上調用底層容器的同名函數。這個函數也能夠用於判斷隊列是否爲空。
(3)priority_queue::top
返回隊頭元素的常引用,隊頭元素是在所設定的比較關係下最大也即優先級最高的元素。此函數實際上調用底層容器的front函數。
(4)priority_queue::pop
清除隊頭元素。
(5)priority_queue::push給隊列插入元素,新元素會按其優先級被排列到適當位置。spa
q.size();//返回q裏元素個數 q.empty();//返回q是否爲空,空則返回1,不然返回0 q.push(k);//在q的末尾插入k q.pop();//刪掉q的第一個元素 q.top();//返回q的第一個元素
3、less和greater優先隊列.net
優先隊列是優先級高的在隊首,定義優先級大小的方式是傳入一個算子的參數比較a, b兩個東西,返回true則a的優先級<b的優先級。code
默認是less算子也就是返回a<b,也就是小的優先級也小,而greater算子返回a>b,小的優先級高。
若是是默認的less算子,值大的優先級高,天然默認的優先隊列大的先出隊。
若是是使用greater算子,值小的優先級高,優先隊列小的先出隊。
priority_queue <int,vector<int>,less<int> > p; priority_queue <int,vector<int>,greater<int> > q;
【默認less算子--優先輸出大數據】
priority_queue<Type, Container, Functional>模板類有三個模板參數,第一個Type是元素類型,第二個Container爲容器類型,第三個Functional是比較算子。其中後兩個均可以省略,默認容器爲vector,默認算子爲less:
less算子,即默認算子爲:大的往前排,小的日後排(出隊時隊列頭的元素出隊,即大者先出隊)。
#include<iostream> #include<queue> using namespace std; int main(){ priority_queue<int> p; p.push(1); p.push(2); p.push(8); p.push(5); p.push(43); while(!q.empty()){ cout<<p.top()<<endl; p.pop(); } return 0; }
【greater算子--優先輸出小數據】
greater算子,即默認算子爲:小的往前排,大的日後排(出隊時隊列頭的元素出隊,即小者先出隊)。
priority_queue<int, vector<int>, greater<int> > p;
#include<iostream> #include<queue> using namespace std; int main(){ priority_queue<int, vector<int>, greater<int> >p; p.push(1); p.push(2); p.push(8); p.push(5); p.push(43); while(!q.empty()){ cout<<p.top()<<endl; p.pop(); } return 0; }
【自定義算子--重載默認的<符號】
#include <iostream> #include <queue> using namespace std; class T { public: int x, y, z; T(int a, int b, int c):x(a), y(b), z(c) { } }; bool operator < (const T &t1, const T &t2) { return t1.z < t2.z; // 按照z 的順序來決定t1 和t2 的順序 } int main() { priority_queue<T> q;//使用模板T的自定義比較方法 q.push(T(4,4,3)); q.push(T(2,2,5)); q.push(T(1,5,4)); q.push(T(3,3,6)); while (!q.empty()) { T t = q.top(); q.pop(); cout << t.x << " " << t.y << " " << t.z << endl; } return 0; }
我的更喜歡把自定義算子寫成友元的,寫進類裏:struct狀況相似
爲了更好地理解自定義算子,下面給出了兩個示例代碼,
其中一個爲上面例子中使用struct,且把自定義算子寫進struct內部的狀況
另外一個爲測試Dijkstra模板中HeapNode的測試代碼;
【源代碼1】
#include <iostream> #include <queue> using namespace std; struct T { public: int x, y, z; T(int a, int b, int c):x(a), y(b), z(c) { } friend bool operator < (const T &t1, const T &t2)//自定義less算子,優先輸出大數據 { ////z值小的往前排,z值大的日後排(出隊時序列尾的元素出隊,即z值大者先出隊) return t1.z < t2.z; // 按照z 的順序來決定t1 和t2 的順序,優先輸出z值大的大數據 // return t2.z > t1.z; } }; int main() { priority_queue<T> q;//使用模板T的自定義比較方法 q.push(T(4,4,3)); q.push(T(2,2,5)); q.push(T(1,5,4)); q.push(T(3,3,6)); while (!q.empty()) { T t = q.top(); q.pop(); cout << t.x << " " << t.y << " " << t.z << endl; } return 0; }
【測試結果1】
3 3 6 2 2 5 1 5 4 4 4 3
【源代碼2】
#include <iostream> #include <queue> using namespace std; struct HeapNode //Dijkstra算法用到的優先隊列的節點 { int d,u; HeapNode(int d,int u):d(d),u(u){} bool operator < (const HeapNode &rhs)const //自定義less算子,優先輸出大數據 { //按照d的順序來決定自身HeapNode和rhs的順序,優先輸出d值大的大數據 //return d > rhs.d; 這兩種寫法是同樣的 return rhs.d<d; //d值小的往前排,d值大的日後排(出隊時序列尾的元素出隊,即d值大者先出隊) } }; int main() { priority_queue<HeapNode> q;//使用模板T的自定義比較方法 q.push(HeapNode(4,3)); q.push(HeapNode(2,5)); q.push(HeapNode(1,4)); q.push(HeapNode(3,6)); while (!q.empty()) { HeapNode n = q.top(); q.pop(); cout << n.d << " " << n.u << endl; } return 0; }
【測試結果2】
1 4 2 5 3 6 4 3
如下例子幫助理解大根堆、小根堆:
#include <iostream> #include <queue> #include <cstdio> using namespace std; int main(int argc, char** argv) { //priority_queue<int,vector<int>,greater<int>>q;//greater是小根堆,從小到大輸出 priority_queue<int,vector<int>,less<int>>q; // less是大根堆, 從大到小輸出 //priority_queue<int>q默認從大到小排序(大根堆) int n; int x; while(cin>>n){ for(int i=0;i<n;i++){ cin>>x; q.push(x); } while(!q.empty()){ int x=q.top(); cout<<x<<" "; q.pop(); } } return 0; }