目录
概述
算法
源码
PriorityQueue.h
test.cpp
测试结果
概述
priority_queue:优先级队列,包含在头文件<queue>中
优先级队列类似于堆结构,优先级最高的元素被置为堆顶,最优先被弹出top()和删除pop()
优先级队列的默认调整策略是大根堆,也就是最大值在堆顶
自定义类型需要用户自己提供 "<" 和 ">" 的重载才能使用优先级队列
元素的每一次插入push(),都是擦在队尾,再从队尾进行一次向上调整adjust_up()
元素的每一次删除pop(),都是删除堆顶元素(先将堆顶元素与末尾元素交换,再尾删),最后再从堆顶进行向下调整adjust_down()
算法
priority_queue优先级队列的设计,成员变量默认为一个vector容器变量,调整策略默认为less,这样大大简化了代码。
priority_queue优先级队列采用堆结构的设计方案,有其独特的特性,但每次插入删除都会进行调整,这样牺牲了部分性能。
用优先级队列调整自定义类型,需要自己提供 "<" 和 ">" 的重载
源码
PriorityQueue.h
#pragma once
#include <iostream>
#include <vector>
template<class T>
class Less
{
public:
bool operator()(const T& x, const T& y)const
{
return x < y;
}
};
template<class T>
class Greater
{
public:
bool operator()(const T& x, const T& y)const
{
return x > y;
}
};
// 默认调整策略为 less,parent比child小则调整,建大根堆
template<class T,class Container = std::vector<T>, class Compare = Less<T>>
class PriorityQueue
{
public:
PriorityQueue()
{}
template<class InputIterator>
PriorityQueue(InputIterator first, InputIterator last)
: _con(first, last)
{
for (size_t i = (_con.size() - 1 - 1) / 2; i >= 0; --i)
{
adjust_down(i);
}
}
void adjust_up(size_t child)
{
Compare com;
size_t parent = (child - 1) / 2;
while (child > 0)
{
if (com(_con[parent], _con[child]))
{
std::swap(_con[child], _con[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
void adjust_down(size_t parent)
{
Compare com;
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]))
{
std::swap(_con[child], _con[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void push(const T& x)
{
_con.push_back(x);
adjust_up(_con.size() - 1);
}
void pop()
{
std::swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
adjust_down(0);
}
const T& top()const
{
return _con[0];
}
bool empty()const
{
return _con.empty();
}
size_t size()const
{
return _con.size();
}
private:
Container _con;
};
test.cpp
#include "PriorityQueue.h"
#include <iostream>
using namespace std;
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
&& _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);
}
bool operator>(const Date& d)const
{
return !(*this < d || *this == d);
}
friend ostream& operator<<(ostream& os, const Date& d)
{
os << d._year << "-" << d._month << "-" << d._day;
return os;
}
private:
int _year, _month, _day;
};
struct PDateLess
{
bool operator()(const Date* d1, const Date* d2)
{
return *d1 < *d2;
}
};
struct PDateGreater
{
bool operator()(const Date* d1, const Date* d2)
{
return *d1 > *d2;
}
};
void Test()
{
// 大堆,需要用户在自定义类型中提供 < 的重载
PriorityQueue<Date> q1;
q1.push(Date(2018, 10, 1));
q1.push(Date(2019, 5, 20));
q1.push(Date(2020, 2, 14));
cout <<"q1.top = " << q1.top() << endl;
while (q1.size())
{
cout << q1.top() << endl;
q1.pop();
}
cout << endl;
// 小堆,需要用户在自定义类型中提供 > 的重载
PriorityQueue<Date, vector<Date>, greater<Date>> q2;
q2.push(Date(2018, 10, 1));
q2.push(Date(2019, 5, 20));
q2.push(Date(2020, 2, 14));
cout << "q2.top = " << q2.top() << endl;
while (q2.size())
{
cout << q2.top() << endl;
q2.pop();
}
cout << endl;
PriorityQueue<Date*, vector<Date*>, PDateLess> q3;
q3.push(new Date(2018, 10, 1));
q3.push(new Date(2019, 5, 20));
q3.push(new Date(2020, 2, 14));
cout << "q3.top = " << *q3.top() << endl;
while (q3.size())
{
cout << *q3.top() << endl;
q3.pop();
}
cout << endl;
PriorityQueue<Date*, vector<Date*>, PDateGreater> q4;
q4.push(new Date(2018, 10, 1));
q4.push(new Date(2019, 5, 20));
q4.push(new Date(2020, 2, 14));
cout << "q4.top = " << *q4.top() << endl;
while (q4.size())
{
cout << *q4.top() << endl;
q4.pop();
}
cout << endl;
}
int main()
{
Test();
return 0;
}
测试结果
文章来源:https://www.toymoban.com/news/detail-432492.html
文章来源地址https://www.toymoban.com/news/detail-432492.html
到了这里,关于【C++】STL之priority_queue类源码剖析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!