具有自定义比较器的最小优先级队列
Posted
技术标签:
【中文标题】具有自定义比较器的最小优先级队列【英文标题】:Min Priority Queue with custom comparator 【发布时间】:2018-10-23 13:28:10 【问题描述】:我正在研究使用优先级队列的排序功能。该函数是模板化的,并接受自定义比较器:
template <class T, class Comparator>
void sort (std::vector<T>& myArray, Comparator comp)
函数创建一个优先级队列:
std::priority_queue<T, std::vector<T>, Comparator > pQueue;
目前,top()
和 pop()
返回并弹出最大值。
但是,我正在寻找一个最小优先级队列,它在使用 top()
和 pop()
函数时返回并弹出最小值。我该怎么做呢?
【问题讨论】:
将比较器的返回值改为负数? (使用!
)
很遗憾无法更改比较器
为什么?你想要一个低优先级队列而不是高优先级队列,然后使用相反的比较器,就是这样。
我运行它的测试用例具有无法更改的比较器
你想通过使pop()
和top()
不是给定比较器的行为方式来实现什么?
【参考方案1】:
std::priority_queue
是一个最大堆(默认),只有最大的元素可用。如果你希望它是一个最小堆,那么你需要反转排序条件。因此,如果comp(a, b)
将返回true
如果a < b
则我们需要交换a
和b
以将std::priority_queue
转换为最小堆。看起来像
template <class T, class Comparator>
void sort (std::vector<T>& myArray, Comparator comp)
auto comp_reverse = [](const auto& lhs, const auto& rhs) return comp(rhs, lhs); ;
std::priority_queue<T, std::vector<T>, decltype(comp_reverse)> pQueue;
//...
【讨论】:
【参考方案2】:只需交换给您的Comparator
对象的参数:
auto cmp = [](auto a, auto b) return Comparator()(b, a); ;
std::priority_queue<int, std::vector<int>, decltype(cmp)> pq(cmp);
请注意,您的Comparator
(即Compare
in std::priority_queue
)必须提供严格的弱排序。
Compare
类型提供严格的弱排序。
然而,lambda 表达式
auto cmp = [](auto a, auto b) return !Comparator()(a, b); ;
可能不提供严格的弱排序。例如,如果Comparator()(a, b)
被定义为a < b
,那么!Comparator()(a, b)
将等价于!(a < b)
,而!(a < b)
又等价于a >= b
,并且绝对不同于a > b
。
与>
运算符不同,>=
运算符是一个二元关系1,它不提供严格的弱排序,因为strictness2 不成立,因为 a >= a
是真的,即它实际上是 reflexive3。
(1) 二元关系 只是一个二元谓词,即一个带有两个参数的布尔函数,例如关系运算符或@987654338 @std::less<int>
的成员函数。
(2) 一个二元关系被称为 strict,如果它对于一个元素和它自己从不持有,例如,<
,因为a < a
永远不会成立。
(3) 一个二元关系被称为自反,如果它对于一个元素和它自己总是成立,例如<=
,因为a <= a
始终成立。
【讨论】:
【参考方案3】:将比较器包装在交换参数顺序的东西中。
a < b
完全等于b > a
。
template <typename Comparator>
struct invert
template <typename Right, typename Left>
bool operator()(Right&& rhs, Left&& lhs)
return comp(std::forward<Left>(lhs), std::forward<Right>(rhs));
Comparator comp;
;
template <class T, class Comparator>
void sort (std::vector<T>& myArray, Comparator comp)
std::priority_queue<T, std::vector<T>, invert<Comparator> > pQueue(comp);
// ...
【讨论】:
以上是关于具有自定义比较器的最小优先级队列的主要内容,如果未能解决你的问题,请参考以下文章