C++中priority_queue的使用與模擬實(shí)現(xiàn)
priority_queue的使用
priority_queue簡介
- 優(yōu)先隊(duì)列是一種容器適配器,有嚴(yán)格的排序標(biāo)準(zhǔn),它的第一個元素總是它所包含的元素中最大的(或最小的)。
- 此上下文類似于堆,在堆中可以隨時插入元素,并且只能檢索最大堆(或 最小堆)元素(優(yōu)先隊(duì)列中位于頂部的元素)。
- 默認(rèn)情況下,如果沒有為特定的priority_queue類實(shí)例化指定容器類,則使用vector。
priority_queue的使用
| 成員函數(shù) | 功能 |
|---|---|
| push | 插入數(shù)據(jù) |
| pop | 刪除優(yōu)先級隊(duì)列中最大(最小)元素,即堆頂元素 |
| top | 返回優(yōu)先級隊(duì)列中最大(最小)元素,即堆頂元素 |
| empty | 檢測優(yōu)先級隊(duì)列是否為空 |
| size | 獲取隊(duì)列中有效元素個數(shù) |
void TestPriorityQueue()
{
// 默認(rèn)情況下,創(chuàng)建的是大堆,其底層按照小于號比較
vector<int> v{ 3, 2, 7, 6, 0, 4, 1, 9, 8, 5 };
priority_queue<int> q1;// 構(gòu)建優(yōu)先級隊(duì)列
for (auto e : v)
q1.push(e);//尾插
cout << "q1中元素個數(shù):" << q1.size() << endl;
for (size_t i = 0;i<v.size();++i)
{
cout << q1.top() << " ";//輸出棧頂?shù)臄?shù)據(jù)
q1.pop();//尾刪
}
cout << endl;
cout << "q1中元素個數(shù):" << q1.size() << endl;
cout << endl;
// 如果要創(chuàng)建小堆,將第三個模板參數(shù)換成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() << " ";//輸出棧頂?shù)臄?shù)據(jù)
q2.pop();//尾刪
}
cout << endl;
}

如果在priority_queue中放自定義類型的數(shù)據(jù),用戶需要在自定義類型中提供> 或者< 的重載。
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;
// 如果要創(chuàng)建小堆,需要用戶提供>的重載
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的模擬實(shí)現(xiàn)
priority_queue的底層實(shí)際上就是堆結(jié)構(gòu),可以參考博主之前寫的有關(guān)堆的文章數(shù)據(jù)結(jié)構(gòu)之堆
namespace nzb
{
//比較方式(使內(nèi)部結(jié)構(gòu)為大堆)
template<class T>
class Less
{
public:
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
//比較方式(使內(nèi)部結(jié)構(gòu)為小堆)
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)
{
//將迭代器中的數(shù)據(jù)插入優(yōu)先級隊(duì)列中
while (first != last)
{
_con.push_back(*first);
first++;
}
//從最后一個非葉子結(jié)點(diǎn)向上調(diào)整
for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(i);
}
}
//堆的向上調(diào)整
void AdjustUp(size_t child)
{
size_t parent = (child - 1) / 2;//找到父節(jié)點(diǎn)
while (child > 0)
{
if (_com(_con[parent], _con[child]))//判斷是否需要交換
{
//交換父子結(jié)點(diǎn)
swap(_con[parent], _con[child]);
//繼續(xù)向上調(diào)整
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
//向下調(diào)整
void AdjustDown(size_t parent)
{
size_t child = parent * 2 + 1;//算出左子節(jié)點(diǎn)的下標(biāo)
while (child < _con.size())
{
//找出子結(jié)點(diǎn)中符合比較方式的值
if (child + 1 < _con.size() && _com(_con[child], _con[child + 1]))
{
child++;
}
//通過所給比較方式確定是否需要交換結(jié)點(diǎn)位置
if (_com(_con[parent], _con[child]))
{
//交換父子結(jié)點(diǎn)
swap(_con[parent], _con[child]);
//繼續(xù)向下調(diào)整
parent = child ;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
//插入數(shù)據(jù)
void push(const T& x)
{
_con.push_back(x);
AdjustUp(_con.size() - 1);//將最后一個元素向上調(diào)整
}
//刪除數(shù)據(jù)
void pop()
{
swap(_con[0], _con[_con.size() - 1]);//交換首尾數(shù)據(jù)
_con.pop_back();//尾刪
AdjustDown(0);//首元素向下調(diào)整
}
//訪問頭元素
const T& top() const
{
return _con[0];
}
//獲取隊(duì)列中有效元素個數(shù)
size_t size()
{
return _con.size();
}
//判空
bool empty()
{
return _con.empty();
}
private:
Container _con;//底層容器
Compare _com;//比較方式
};
}
到此這篇關(guān)于C++中priority_queue的使用與模擬實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C++ priority_queue內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++貪心算法實(shí)現(xiàn)活動安排問題(實(shí)例代碼)
貪心算法(又稱貪婪算法)是指,在對問題求解時,總是做出在當(dāng)前看來是最好的選擇。這篇文章主要介紹了C++貪心算法實(shí)現(xiàn)活動安排問題,需要的朋友可以參考下2019-11-11
C++利用對象池優(yōu)化內(nèi)存管理解決MISRA報(bào)警的代碼詳解
本篇詳細(xì)講解如何用對象池技術(shù)優(yōu)化C++項(xiàng)目中的內(nèi)存管理,徹底消除new/delete帶來的MISRA報(bào)警,兼顧高性能與安全規(guī)范,需要的朋友可以參考下2025-07-07
C++命名空間using?namespace?std是什么意思
namespace中文意思是命名空間或者叫名字空間,傳統(tǒng)的C++只有一個全局的namespace,下面這篇文章主要給大家介紹了關(guān)于C++命名空間using?namespace?std是什么意思的相關(guān)資料,需要的朋友可以參考下2023-01-01
C語言實(shí)現(xiàn)掃雷小游戲(擴(kuò)展版可選擇游戲難度)
游戲目標(biāo)是找出所有沒有地雷的方格,完成游戲;要是按了有地雷的方格,游戲失?。煌婕铱蓸?biāo)記雷的位置,游戲以完成時間來評高低,并且用戶可以選擇游戲難度2019-10-10
C++實(shí)現(xiàn)LeetCode(347.前K個高頻元素)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(347.前K個高頻元素),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
C語言中的自定義類型之結(jié)構(gòu)體與枚舉和聯(lián)合詳解
今天我們來學(xué)習(xí)一下自定義類型,自定義類型包括結(jié)構(gòu)體、枚舉、聯(lián)合體,小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考2022-06-06

