priority_queue的常见用法详解
目錄
- 前言
- priorithy_queue的定義
- priority_queue容器內元素的訪問
- priority_queue常用函數
- priority_queue內元素優先級的設置
- priority_queue的常見用途
前言
priority_queue又稱為優先隊列,其底層是用堆來進行實現的。在優先隊列中,隊首元素一定是當前隊列中優先級最高的那一個(默認是大根堆)。
例如在隊列有如下元素,且定義好了優先級:
當然,可以在任何時候往優先隊列里面加入(push)元素。而優先隊列底層的數據結構堆(heap)會隨時調整結構,
使得每次的隊首元素都是優先級最大的。
關于這里的優先級是規定出來的。例如上面的例子中,也可以規定數字越小的優先級越大。
priorithy_queue的定義
要使用優先隊列,需要的頭文件:
#inlcude<queue>需要的其他東西:
using namespace std;其定義的寫法和其他STL容器相同,typename可以是任意基本數據類型或容器:
priority_queue<typename>name;priority_queue容器內元素的訪問
和隊列不一樣的是,優先隊列沒有front()和back()函數,
而只能通過top()函數來訪問隊首元素(也可以稱為堆頂元素),也就是優先級最高的元素。
priority_queue常用函數
(1)push()
push(x)將令x入隊,時間復雜度為O(logN),其中N為當前優先隊列中的元素個數。
(2)top()
top()可以獲得隊首元素(即堆頂元素),時間復雜度為O(1)。
(3)pop()
pop()令隊首元素(即堆頂元素)出隊,時間復雜度為O(logN),其中N為當前優先隊列中的元素個數。
(4)empty()
empty()檢測優先隊列是否為空,返回true則為空,返回false則為非空。時間復雜度為O(1)。
(5)size()
size()返回優先隊列內元素的個數,時間復雜度為O(1)。
priority_queue內元素優先級的設置
如何定義優先級隊列內元素的優先級是運用好優先隊列的關鍵,下面分別介紹基本數據類型
(例如 int 、double、char)與結構體類型的優先級設置方法。
(1)基本數據類型的優先級設置
此處指的基本數據類型就是int型、double 型、char型等可以直接使用的數據類型,優先隊列對它們的優先級設置般是數字大的優先級越高, 因此隊首元索就是優先隊列內元素最大的那個(如果char 型,則是字典序最大的)。
對基本數據類型來說,下面兩種優先隊列的定義是等價的(以int型為例,注意最后兩個>之間有一個空格):
可以發現,第二種定義方式的尖括號內多出了兩個參數:一個是vector,另一個是less.其中vector (也就是第二個參數)填寫的是來承載底層數據結構堆(heap)的容器,如果第一個參數是double型或char型,則此處只需要填寫vector-或vector;而第三個參數less-則是對第一個參數的比較類, less表示數字大的優先級越大,而greater表示數字小的優先級越大。
因此,如果想讓優先隊列總是把最小的元素放在隊首,只需進行如下定義:
下面是一個示例:
事實上,即便是基本數據類型,也可以使用下面講解的結構體的優先級設置方法,只不過第三個參數的寫法不太一樣了。
下面看一下結構體的優先級的設置方法。
(2)結構體的優先級設置
以一個水果的名稱和價格為例:
現在希望按水果的價格高的為優先級高,就需要重載( overload )小于號 " < "。重載是指對已有的運算符進行重新定義,
也就是說,可以改變小于號的功能(例如把它重載為大于號的功能)
同理,如果想要以價格低的水果為優先級高,那么只需要把return 中的小于號改為大于號即可。
struct fruit {string name;int price;friend bool operator < (fruit f1,fruit f2){return f1.price > f2.price;} };
讀者會發現,此處對小于號的重載與排序函數sort中的cmp函數有些相似,它們的參數都是兩個變量,函數內部都是return了true或者false,
事實上,這兩者的作用確實是類似的只不過效果看上去似乎是“相反”的。在排序中,如果是“return f1.price > f2.price",
那么則是按價格從高到低排序,但是在優先隊列中卻是把價格低的放到隊首。原因在于,優先隊列本身默認的規則就是優先級高的放在隊首,因此把小于號重載為大于號的功能時只是把這個規則反向一下。
如果讀者無法理解,那么不妨記住,優先隊列的這個函數與sort()中的cmp函數的效果是相反的。
那么,有沒有辦法跟sort() 中的cmp函數那樣寫在結構體外面呢? 自然是有辦法的。
只需要把friend 去掉, 把小于號改成一對小括號,然后把重載的函數寫在結構體外面,同時將其用
struct包裝起來。
在這種情況下,需要用之前講解的第二種定義方式來定義優先隊列:
priority_queue<fruit,vector<fruit>,cmp> q;可以看到此處只是把greater()部分換成了cmp
即便是基本數據類型或者其他STL容器(例如 set),也可以通過同樣的方式來定義優先級。
如果結構體內的數據較為龐大(例如出現了字符串或數組),建議使用引用來提高效率。
此時比較類的參數中需要加上"const “和” &" 。
priority_queue的常見用途
priority_queue可以解決一些貪心問題,也可以對Dijkstra算法進行優化(因為優先隊列的本質是堆)
有一點需要注意的是,使用pop()函數前,必須用empty()判斷優先隊列是否為空,否則可能因為隊空而出現錯誤。
總結
以上是生活随笔為你收集整理的priority_queue的常见用法详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: queue的常见用法详解
- 下一篇: pair的常见用法详解