在[1]對常用的STL容器進行了概覽,筆者在刷題過程中經常需要查詢一些STL容器的函數,實爲不便,因此在此對STL容器中常用的操作進行筆記。
std::priority_queue<T>
定義於頭文件<queue>
中,是所謂的優先隊列,一般的隊列,如同[2]中所示,是先進先出的,不需要對插入對象的大小或者其他屬性進行排序等,而優先隊列可以提供插入對象與現存對象之間的比較機制,這種機制可以給每個元素提供優先級,從而在隊列出列時,可以按照優先級的大小,升序或者降序出列。這種機制在實現操作系統的ready進程出列,給CPU運算時經常使用,因爲不同的進程是有優先級的,經常需要按照進程的優先級進行出列。
注意到priority_queue<T>
並不是一種原生的序列數據結構,而是一種容器類序列數據結構,其意思是,實現優先隊列的底層數據結構可以是vector<T>
,也可以是deque<T>
,只要是滿足可以定義以下函數的數據類型都行:front()
, push_back()
, pop_back()
。
其類原型如:
template<
class T,
class Container = std::vector<T>,
class Compare = std::less<typename Container::value_type>
> class priority_queue;
這裏的Container
就是在指定容器類型,默認是用vector<T>
實現的;Compare
指定比較元素的方法,默認是less<T>
降序,這裏的less<T>
的意思是最大優先級的元素將會在top()
出現,而相反的,greater<T>
的意思是最小優先級的元素將會在top()
出現。 注意到,優先隊列可以對最大或者最小優先級的元素在常數時間內的查找,但是插入和刪除時間都是對數級別的。 其常用操作也不多,如下例子所示:
push()
插入元素,並且對底層容器排序pop()
彈出棧頂元素,注意不返回值top()
返回棧頂元素,注意不彈出empty()
判斷隊列是否爲空size()
返回隊列尺寸
priority_queue<int, vector<int>, less<int>> lessq;
priority_queue<int, vector<int>, greater<int>> greatq;
vector<int> nums = {2,3,6,8,0,1,5}; // 假設數值大小表示每個元素的優先級
for (auto &n:nums) {
lessq.push(n);
greatq.push(n);
}
while (!lessq.empty()){
cout << lessq.top() << " ";
lessq.pop();
} // 輸出 8,6,5,3,2,1,0 大優先級的先出列
while (!greatq.empty()){
cout << greatq.top() << " ";
greatq.pop();
} // 輸出 0,1,2,3,5,6,8 小優先級的先出列
也可以自定義比較函數:
struct node {
int x, y;
node(int x, int y):x(x), y(y){}
};
struct cmp {
bool operator()(node a, node b){
if (a.x == b.x) return a.y >= b.y;
else return a.x > b.x;
}
};
int main() {
priority_queue<node, vector<node>, cmp> pq;
for(int i = 1; i <= 5; i++)
for(int j = 1; j <= 5; j++)
pq.push(node(i,j));
while (!pq.empty()) {
cout << pq.top().x <<" " << pq.top().y <<endl;
pq.pop();
}
return 0;
}
輸出如:
我們可以發現,priority_queue<T>
是一個最大堆,其默認使用std:less<T>
,也就意味着,其使用了操作符operator<
。這意味着如果這個比較返回false
,那麼第一個參數的元素位置將會和top()
更接近[4]。
因此 less<int>
等價於下面的自定義比較結構cmp
struct cmp {
bool operator()(int a, int b) {
return a < b; // 這裏是小於號,也即是爲什麼叫`less`的原因,但是其實最大優先級的先出列。
}
}
Reference
[1]. https://blog.csdn.net/LoseInVain/article/details/104189784
[2]. https://blog.csdn.net/LoseInVain/article/details/104453697
[3]. https://stackoverflow.com/questions/16111337/declaring-a-priority-queue-in-c-with-a-custom-comparator
[4]. https://stackoverflow.com/questions/36069276/what-does-the-return-value-of-a-priority-queue-custom-comparator-signify