C++中priority_queue的實(shí)現(xiàn)
一、priority_queue 核心定義
std::priority_queue(優(yōu)先隊(duì)列)是 C++ STL 中的適配器容器(基于其他容器實(shí)現(xiàn)),本質(zhì)是一個(gè)「堆結(jié)構(gòu)」——隊(duì)列中的元素會按照優(yōu)先級自動排序,而非按插入順序。
- 核心特性:每次訪問/彈出的都是優(yōu)先級最高的元素(默認(rèn)是最大值,可自定義為最小值);
- 底層實(shí)現(xiàn):默認(rèn)基于
std::vector,也可指定std::deque(不支持std::list,因?yàn)槎研枰S機(jī)訪問); - 頭文件:必須包含
<queue>。
二、基本用法(默認(rèn)大頂堆)
1. 初始化與核心操作
#include <iostream>
#include <queue> // 必須包含
using namespace std;
int main() {
// 1. 初始化:默認(rèn)是大頂堆(最大值優(yōu)先)
priority_queue<int> pq;
// 2. 插入元素(push):O(log n) 復(fù)雜度
pq.push(3);
pq.push(1);
pq.push(5);
pq.push(2);
// 3. 訪問隊(duì)首(top):返回優(yōu)先級最高的元素(最大值)
cout << "隊(duì)首元素(最大值):" << pq.top() << endl; // 輸出:5
// 4. 彈出隊(duì)首(pop):刪除優(yōu)先級最高的元素,O(log n) 復(fù)雜度
pq.pop();
cout << "彈出后隊(duì)首:" << pq.top() << endl; // 輸出:3
// 5. 判空(empty)、大?。╯ize)
cout << "是否為空:" << (pq.empty() ? "是" : "否") << endl; // 輸出:否
cout << "元素個(gè)數(shù):" << pq.size() << endl; // 輸出:3
// 6. 遍歷(無迭代器,需彈出所有元素)
while (!pq.empty()) {
cout << pq.top() << " "; // 輸出:3 2 1
pq.pop();
}
return 0;
}2. 關(guān)鍵說明
top():僅返回隊(duì)首元素,不刪除;pop():僅刪除隊(duì)首元素,無返回值(需先top()再pop());- 無
clear()成員函數(shù):清空優(yōu)先隊(duì)列需手動彈出所有元素,或賦值空隊(duì)列(pq = priority_queue<int>();); - 不支持隨機(jī)訪問:無法直接訪問中間元素,只能通過
top()訪問隊(duì)首。
三、自定義優(yōu)先級(小頂堆/自定義規(guī)則)
默認(rèn)的 priority_queue 是「大頂堆」(最大值優(yōu)先),可通過以下方式修改優(yōu)先級:
1. 實(shí)現(xiàn)小頂堆(最小值優(yōu)先)
方式1:指定比較函數(shù) greater<T>
#include <iostream>
#include <queue>
#include <vector> // 顯式指定底層容器
using namespace std;
int main() {
// 模板參數(shù):<元素類型, 底層容器類型, 比較函數(shù)>
priority_queue<int, vector<int>, greater<int>> pq;
pq.push(3);
pq.push(1);
pq.push(5);
pq.push(2);
cout << "小頂堆隊(duì)首(最小值):" << pq.top() << endl; // 輸出:1
pq.pop();
cout << "彈出后隊(duì)首:" << pq.top() << endl; // 輸出:2
return 0;
}
方式2:對元素取反(適用于簡單類型)
// 插入時(shí)取反,彈出時(shí)再取反,模擬小頂堆 priority_queue<int> pq; pq.push(-3); pq.push(-1); pq.push(-5); pq.push(-2); cout << "模擬小頂堆隊(duì)首:" << -pq.top() << endl; // 輸出:1
2. 自定義結(jié)構(gòu)體/類的優(yōu)先級
需重載比較運(yùn)算符(operator<),或自定義比較函數(shù)。
示例:結(jié)構(gòu)體按指定字段排序
#include <iostream>
#include <queue>
#include <string>
using namespace std;
// 定義結(jié)構(gòu)體:存儲學(xué)生姓名和分?jǐn)?shù)
struct Student {
string name;
int score;
// 重載 < 運(yùn)算符(注意:優(yōu)先隊(duì)列用 < 比較,且規(guī)則與直覺相反)
// 需求:分?jǐn)?shù)高的優(yōu)先級高(大頂堆)
bool operator<(const Student& other) const {
// 若 this->score < other.score,則 other 優(yōu)先級更高
return score < other.score;
}
};
int main() {
priority_queue<Student> pq;
pq.push({"Alice", 85});
pq.push({"Bob", 92});
pq.push({"Charlie", 78});
// 輸出優(yōu)先級最高的元素(分?jǐn)?shù)最高的Bob)
cout << "最高分:" << pq.top().name << " " << pq.top().score << endl; // Bob 92
pq.pop();
cout << "次高分:" << pq.top().name << " " << pq.top().score << endl; // Alice 85
return 0;
}
自定義比較函數(shù)(適用于復(fù)雜規(guī)則)
#include <iostream>
#include <queue>
#include <string>
#include <functional> // 需包含(for function)
using namespace std;
struct Student {
string name;
int score;
};
// 自定義比較函數(shù):分?jǐn)?shù)低的優(yōu)先級高(小頂堆)
struct CompareStudent {
bool operator()(const Student& a, const Student& b) {
return a.score > b.score; // 與小頂堆的 greater 邏輯一致
}
};
int main() {
priority_queue<Student, vector<Student>, CompareStudent> pq;
pq.push({"Alice", 85});
pq.push({"Bob", 92});
pq.push({"Charlie", 78});
cout << "最低分:" << pq.top().name << " " << pq.top().score << endl; // Charlie 78
return 0;
}
四、底層原理:堆結(jié)構(gòu)
priority_queue 的核心是二叉堆(完全二叉樹),所有操作均基于堆的特性:
- 插入(push):將元素添加到堆尾,然后「上?。╯ift up)」調(diào)整堆,確保父節(jié)點(diǎn)優(yōu)先級高于子節(jié)點(diǎn)(O(log n));
- 彈出(pop):將堆頂元素與堆尾元素交換,刪除堆尾,然后「下沉(sift down)」調(diào)整堆(O(log n));
- 訪問隊(duì)首(top):直接返回堆頂元素(O(1))。
五、常見應(yīng)用場景
- Top K 問題:如找數(shù)組中前 K 大/前 K 小的元素(用小頂堆存前 K 大,大頂堆存前 K 小);
// 示例:找數(shù)組中前3大的元素 vector<int> nums = {5, 2, 9, 1, 7, 6, 8}; priority_queue<int, vector<int>, greater<int>> pq; // 小頂堆 for (int num : nums) { pq.push(num); if (pq.size() > 3) pq.pop(); // 保持堆大小為3 } // 此時(shí)堆中是前3大的元素(7,8,9),但順序是從小到大 - 貪心算法:如任務(wù)調(diào)度、哈夫曼編碼、最短路徑(Dijkstra 算法);
- 實(shí)時(shí)排序:需頻繁獲取最大值/最小值的場景(如事件優(yōu)先級處理)。
六、注意事項(xiàng)
- 底層容器限制:只能用支持隨機(jī)訪問的容器(
vector/deque),不能用list(無隨機(jī)訪問); - 比較函數(shù)規(guī)則:
- 默認(rèn)
less<T>:大頂堆(a < b則 b 優(yōu)先級高); greater<T>:小頂堆(a > b則 b 優(yōu)先級高);
- 默認(rèn)
- 性能:插入/彈出為 O(log n),訪問隊(duì)首為 O(1),遍歷需彈出所有元素(O(n log n));
- 線程安全:無內(nèi)置線程安全,多線程需手動加鎖。
總結(jié)
| 核心特性 | 說明 |
|---|---|
| 排序規(guī)則 | 默認(rèn)大頂堆,可自定義為小頂堆/自定義規(guī)則 |
| 核心操作 | push(插入)、top(查隊(duì)首)、pop(刪隊(duì)首) |
| 時(shí)間復(fù)雜度 | push/pop: O(log n),top: O(1) |
| 底層容器 | 默認(rèn) vector,可指定 deque |
| 適用場景 | Top K、貪心算法、實(shí)時(shí)優(yōu)先級處理 |
priority_queue 是 C++ 中處理「優(yōu)先級排序」的核心容器,重點(diǎn)掌握自定義優(yōu)先級的兩種方式(greater<T>/自定義比較函數(shù)),以及 Top K 問題的經(jīng)典用法。
到此這篇關(guān)于C++中priority_queue的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C++ priority_queue內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- c++ priority_queue用法入門超詳細(xì)教程
- C++ 中"priority_queue" 優(yōu)先級隊(duì)列實(shí)例詳解
- c++中priority_queue模擬的實(shí)現(xiàn)
- 深入了解C++優(yōu)先隊(duì)列(priority_queue)的使用方法
- C++中priority_queue與仿函數(shù)實(shí)現(xiàn)方法
- C++中STL的優(yōu)先隊(duì)列priority_queue詳解
- C++中priority_queue模擬實(shí)現(xiàn)的代碼示例
- C++ 容器適配器priority_queue的使用及實(shí)現(xiàn)代碼
- 詳解c++優(yōu)先隊(duì)列priority_queue的用法
- 詳解C++模擬實(shí)現(xiàn)priority_queue(仿函數(shù))
- C++深入刨析優(yōu)先級隊(duì)列priority_queue的使用
相關(guān)文章
C++中std::forward的實(shí)現(xiàn)示例
std::forward是C++11引入的完美轉(zhuǎn)發(fā)工具,它通過引用折疊規(guī)則保留參數(shù)的原始值類別和屬性,確保目標(biāo)函數(shù)接收到與輸入一致的參數(shù)類型,下面就來介紹一下如何使用,感興趣的可以了解一下2026-01-01
c++ std::sort使用自定義的比較函數(shù)排序方式
文章介紹了使用std::sort對容器內(nèi)元素進(jìn)行排序的基本方法,包括自定義排序函數(shù)和在類中調(diào)用自定義成員函數(shù)進(jìn)行排序的方法,文章還指出了在傳遞成員函數(shù)指針時(shí)可能會遇到的錯(cuò)誤,并提供了使用Lambda表達(dá)式的解決辦法2025-02-02
C語言輸入一個(gè)數(shù)判斷是否為素?cái)?shù)的多種方法
素?cái)?shù)是只能被1和它自己本身整除,不能被其他自然數(shù)整除的大于1的正整數(shù),下面這篇文章主要給大家介紹了關(guān)于C語言輸入一個(gè)數(shù)判斷是否為素?cái)?shù)的多種方法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04
基于C語言實(shí)現(xiàn)個(gè)人通訊錄管理系統(tǒng)
使用Qt實(shí)現(xiàn)監(jiān)聽網(wǎng)頁是否響應(yīng)并導(dǎo)出Excel表
C和C++中實(shí)現(xiàn)對數(shù)據(jù)的流加密RC4算法

