C++中priority_queue的使用與模擬實現
priority_queue的使用
priority_queue文檔介紹
priority_queue簡介
- 優先隊列是一種容器適配器,有嚴格的排序標準,它的第一個元素總是它所包含的元素中最大的(或最小的)。
- 此上下文類似於堆,在堆中可以隨時插入元素,並且隻能檢索最大堆(或 最小堆)元素(優先隊列中位於頂部的元素)。
- 默認情況下,如果沒有為特定的priority_queue類實例化指定容器類,則使用vector。
priority_queue的使用
成員函數 | 功能 |
---|---|
push | 插入數據 |
pop | 刪除優先級隊列中最大(最小)元素,即堆頂元素 |
top | 返回優先級隊列中最大(最小)元素,即堆頂元素 |
empty | 檢測優先級隊列是否為空 |
size | 獲取隊列中有效元素個數 |
void TestPriorityQueue() { // 默認情況下,創建的是大堆,其底層按照小於號比較 vector<int> v{ 3, 2, 7, 6, 0, 4, 1, 9, 8, 5 }; priority_queue<int> q1;// 構建優先級隊列 for (auto e : v) q1.push(e);//尾插 cout << "q1中元素個數:" << q1.size() << endl; for (size_t i = 0;i<v.size();++i) { cout << q1.top() << " ";//輸出棧頂的數據 q1.pop();//尾刪 } cout << endl; cout << "q1中元素個數:" << q1.size() << endl; cout << endl; // 如果要創建小堆,將第三個模板參數換成greater比較方式 priority_queue<int, vector<int>, greater<int>> q2(v.begin(), v.end()); for (size_t i = 0; i<v.size(); ++i) { cout << q2.top() << " ";//輸出棧頂的數據 q2.pop();//尾刪 } cout << endl; }
如果在priority_queue中放自定義類型的數據,用戶需要在自定義類型中提供> 或者< 的重載。
class Date { public: Date(int year = 1900, int month = 1, int day = 1) : _year(year) , _month(month) , _day(day) {} bool operator<(const Date& d)const { return (_year < d._year) || (_year == d._year && _month < d._month) || (_year == d._year && _month == d._month && _day < d._day); } bool operator>(const Date& d)const { return (_year > d._year) || (_year == d._year && _month > d._month) || (_year == d._year && _month == d._month && _day > d._day); } friend ostream& operator<<(ostream& _cout, const Date& d) { _cout << d._year << "-" << d._month << "-" << d._day; return _cout; } private: int _year; int _month; int _day; }; void TestPriorityQueue() { // 大堆,需要用戶在自定義類型中提供<的重載 priority_queue<Date> q1; q1.push(Date(2022, 1, 7)); q1.push(Date(2022, 1, 1)); q1.push(Date(2022, 1, 31)); cout << q1.top() << endl; cout << endl; // 如果要創建小堆,需要用戶提供>的重載 priority_queue<Date, vector<Date>, greater<Date>> q2; q2.push(Date(2022, 1, 7)); q2.push(Date(2022, 1, 1)); q2.push(Date(2022, 1, 31)); cout << q2.top() << endl; }
priority_queue的模擬實現
priority_queue的底層實際上就是堆結構,可以參考博主之前寫的有關堆的文章數據結構之堆
namespace nzb { //比較方式(使內部結構為大堆) template<class T> class Less { public: bool operator()(const T& x, const T& y) { return x < y; } }; //比較方式(使內部結構為小堆) template<class T> class Greater { public: bool operator()(const T& x, const T& y) { return x > y; } }; template<class T, class Container = vector<T>, class Compare = Less<T>> class priority_queue { public: priority_queue() {} template<class InputIterator> priority_queue(InputIterator first, InputIterator last) { //將迭代器中的數據插入優先級隊列中 while (first != last) { _con.push_back(*first); first++; } //從最後一個非葉子結點向上調整 for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--) { AdjustDown(i); } } //堆的向上調整 void AdjustUp(size_t child) { size_t parent = (child - 1) / 2;//找到父節點 while (child > 0) { if (_com(_con[parent], _con[child]))//判斷是否需要交換 { //交換父子結點 swap(_con[parent], _con[child]); //繼續向上調整 child = parent; parent = (child - 1) / 2; } else { break; } } } //向下調整 void AdjustDown(size_t parent) { size_t child = parent * 2 + 1;//算出左子節點的下標 while (child < _con.size()) { //找出子結點中符合比較方式的值 if (child + 1 < _con.size() && _com(_con[child], _con[child + 1])) { child++; } //通過所給比較方式確定是否需要交換結點位置 if (_com(_con[parent], _con[child])) { //交換父子結點 swap(_con[parent], _con[child]); //繼續向下調整 parent = child ; child = parent * 2 + 1; } else { break; } } } //插入數據 void push(const T& x) { _con.push_back(x); AdjustUp(_con.size() - 1);//將最後一個元素向上調整 } //刪除數據 void pop() { swap(_con[0], _con[_con.size() - 1]);//交換首尾數據 _con.pop_back();//尾刪 AdjustDown(0);//首元素向下調整 } //訪問頭元素 const T& top() const { return _con[0]; } //獲取隊列中有效元素個數 size_t size() { return _con.size(); } //判空 bool empty() { return _con.empty(); } private: Container _con;//底層容器 Compare _com;//比較方式 }; }
到此這篇關於C++中priority_queue的使用與模擬實現的文章就介紹到這瞭,更多相關C++ priority_queue內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- C++中priority_queue模擬實現的代碼示例
- C++ STL priority_queue自定義排序實現方法詳解
- C++進一步認識類與對象
- C++優先隊列用法案例詳解
- C++日期類(Date)實現的示例代碼