C++中priority_queue的使用與模擬實(shí)現(xiàn)
priority_queue的使用
priority_queue簡(jiǎn)介
- 優(yōu)先隊(duì)列是一種容器適配器,有嚴(yán)格的排序標(biāo)準(zhǔn),它的第一個(gè)元素總是它所包含的元素中最大的(或最小的)。
- 此上下文類(lèi)似于堆,在堆中可以隨時(shí)插入元素,并且只能檢索最大堆(或 最小堆)元素(優(yōu)先隊(duì)列中位于頂部的元素)。
- 默認(rèn)情況下,如果沒(méi)有為特定的priority_queue類(lèi)實(shí)例化指定容器類(lèi),則使用vector。
priority_queue的使用
| 成員函數(shù) | 功能 |
|---|---|
| push | 插入數(shù)據(jù) |
| pop | 刪除優(yōu)先級(jí)隊(duì)列中最大(最小)元素,即堆頂元素 |
| top | 返回優(yōu)先級(jí)隊(duì)列中最大(最小)元素,即堆頂元素 |
| empty | 檢測(cè)優(yōu)先級(jí)隊(duì)列是否為空 |
| size | 獲取隊(duì)列中有效元素個(gè)數(shù) |
void TestPriorityQueue()
{
// 默認(rèn)情況下,創(chuàng)建的是大堆,其底層按照小于號(hào)比較
vector<int> v{ 3, 2, 7, 6, 0, 4, 1, 9, 8, 5 };
priority_queue<int> q1;// 構(gòu)建優(yōu)先級(jí)隊(duì)列
for (auto e : v)
q1.push(e);//尾插
cout << "q1中元素個(gè)數(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中元素個(gè)數(shù):" << q1.size() << endl;
cout << endl;
// 如果要?jiǎng)?chuàng)建小堆,將第三個(gè)模板參數(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中放自定義類(lèi)型的數(shù)據(jù),用戶(hù)需要在自定義類(lèi)型中提供> 或者< 的重載。
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()
{
// 大堆,需要用戶(hù)在自定義類(lèi)型中提供<的重載
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;
// 如果要?jiǎng)?chuàng)建小堆,需要用戶(hù)提供>的重載
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),可以參考博主之前寫(xiě)的有關(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)先級(jí)隊(duì)列中
while (first != last)
{
_con.push_back(*first);
first++;
}
//從最后一個(gè)非葉子結(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++;
}
//通過(guò)所給比較方式確定是否需要交換結(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);//將最后一個(gè)元素向上調(diào)整
}
//刪除數(shù)據(jù)
void pop()
{
swap(_con[0], _con[_con.size() - 1]);//交換首尾數(shù)據(jù)
_con.pop_back();//尾刪
AdjustDown(0);//首元素向下調(diào)整
}
//訪問(wèn)頭元素
const T& top() const
{
return _con[0];
}
//獲取隊(duì)列中有效元素個(gè)數(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
va_list(),va_start(),va_arg(),va_end() 詳細(xì)解析
這些宏定義在stdarg.h中,所以用到可變參數(shù)的程序應(yīng)該包含這個(gè)頭文件.下面我們寫(xiě)一個(gè)簡(jiǎn)單的可變參數(shù)的函數(shù),該函數(shù)至少有一個(gè)整數(shù)參數(shù),第二個(gè)參數(shù)也是整數(shù),是可選的.函數(shù)只是打印這兩個(gè)參數(shù)的值2013-09-09
C語(yǔ)言中pthread_create函數(shù)實(shí)現(xiàn)向線(xiàn)程函數(shù)傳遞參數(shù)
本文主要介紹了C語(yǔ)言中pthread_create函數(shù)實(shí)現(xiàn)向線(xiàn)程函數(shù)傳遞參數(shù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05
C語(yǔ)言控制臺(tái)實(shí)現(xiàn)字符飛機(jī)大戰(zhàn)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言控制臺(tái)實(shí)現(xiàn)字符飛機(jī)大戰(zhàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12
C語(yǔ)言中main函數(shù)兩個(gè)參數(shù)的作用
這篇文章主要介紹了C語(yǔ)言中main函數(shù)兩個(gè)參數(shù)的作用,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09
C語(yǔ)言JNI的動(dòng)態(tài)注冊(cè)詳解
這篇文章主要介紹了JAVA JNI的動(dòng)態(tài)注冊(cè),這里提供簡(jiǎn)單實(shí)例代碼,需要的朋友可以參考下,小編覺(jué)得寫(xiě)的還不錯(cuò),希望能給你帶來(lái)幫助2021-08-08
C++實(shí)現(xiàn)“隱藏實(shí)現(xiàn),開(kāi)放接口”的方案
本文從一個(gè)實(shí)例講解了C++實(shí)現(xiàn)“隱藏實(shí)現(xiàn),開(kāi)放接口”的方案,文章條理清新,內(nèi)容充實(shí),需要的朋友可以參考下2015-07-07
c++將引用或者是指針作為函數(shù)參數(shù)實(shí)現(xiàn)實(shí)參的運(yùn)算
這篇文章主要介紹了c++將引用或者是指針作為函數(shù)參數(shù)實(shí)現(xiàn)實(shí)參的運(yùn)算,需要的朋友可以參考下2014-05-05

