日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

priority_queue的常见用法详解

發布時間:2025/3/20 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 priority_queue的常见用法详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 前言
  • priorithy_queue的定義
  • priority_queue容器內元素的訪問
  • priority_queue常用函數
  • priority_queue內元素優先級的設置
  • priority_queue的常見用途

前言

priority_queue又稱為優先隊列,其底層是用堆來進行實現的。在優先隊列中,隊首元素一定是當前隊列中優先級最高的那一個(默認是大根堆)。
例如在隊列有如下元素,且定義好了優先級:

桃子(優先級3) 梨子(優先級4) 蘋果(優先級1) 那么出隊的順序為: 梨子(4)->桃子(3)->蘋果(1)

當然,可以在任何時候往優先隊列里面加入(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型為例,注意最后兩個>之間有一個空格):

priority_queue<int> q; priority_queue<int , vector<int> , less<int> > q;

可以發現,第二種定義方式的尖括號內多出了兩個參數:一個是vector,另一個是less.其中vector (也就是第二個參數)填寫的是來承載底層數據結構堆(heap)的容器,如果第一個參數是double型或char型,則此處只需要填寫vector-或vector;而第三個參數less-則是對第一個參數的比較類, less表示數字大的優先級越大,而greater表示數字小的優先級越大。
因此,如果想讓優先隊列總是把最小的元素放在隊首,只需進行如下定義:

priority_queue<int, vector<int>, greater<int> >a;

下面是一個示例:

事實上,即便是基本數據類型,也可以使用下面講解的結構體的優先級設置方法,只不過第三個參數的寫法不太一樣了。
下面看一下結構體的優先級的設置方法。
(2)結構體的優先級設置
以一個水果的名稱和價格為例:

struct fruit {string name;int price; };

現在希望按水果的價格高的為優先級高,就需要重載( overload )小于號 " < "。重載是指對已有的運算符進行重新定義,
也就是說,可以改變小于號的功能(例如把它重載為大于號的功能)

struct fruit {string name;int price;friend bool operator < (fruit f1,fruit f2){return f1.peice<f2.price;} };

priority_queue<fruit> q;

同理,如果想要以價格低的水果為優先級高,那么只需要把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包裝起來。

struct cmp {bool operator () (fruit f1,fruit f2){return f1.price>f2.price;} };

在這種情況下,需要用之前講解的第二種定義方式來定義優先隊列:

priority_queue<fruit,vector<fruit>,cmp> q;

可以看到此處只是把greater()部分換成了cmp

即便是基本數據類型或者其他STL容器(例如 set),也可以通過同樣的方式來定義優先級。
如果結構體內的數據較為龐大(例如出現了字符串或數組),建議使用引用來提高效率。
此時比較類的參數中需要加上"const “和” &" 。

friend bool operator < (const fruit &f1,const fruit &f2) {return f1.price>f2.price; } bool operator () (const fruit &f1, const fruit &f2) {return f1.price>f2.price; }

priority_queue的常見用途

priority_queue可以解決一些貪心問題,也可以對Dijkstra算法進行優化(因為優先隊列的本質是堆)
有一點需要注意的是,使用pop()函數前,必須用empty()判斷優先隊列是否為空,否則可能因為隊空而出現錯誤。

總結

以上是生活随笔為你收集整理的priority_queue的常见用法详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。