带有自定义比较器的最小优先级队列

时间:2018-10-23 13:28:10

标签: c++ stl priority-queue

我正在使用优先级队列的排序功能。该函数已模板化,并带有自定义比较器:

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()函数时返回并弹出最小值。我应该怎么做?

3 个答案:

答案 0 :(得分:2)

std::priority_queue是最大堆(默认情况下),并且只有最大的元素可用。如果希望它是最小堆,则需要反转排序条件。因此,如果comp(a, b)如果true会返回a < b,则我们需要交换ab以将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;
    //...
}

答案 1 :(得分: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

>运算符不同,>=运算符是二进制关系 1 ,它不提供严格弱排序 em>,因为 strictness 2 不成立,因为确实a >= a(即实际上是反身 ) 3


(1)二进制关系只是一个二进制谓词,即具有两个参数的布尔函数,例如关系运算符或{{ {} {1}}的成员函数。

(2)二进制关系,如果它从不对表示保留,则称为严格,例如operator() ,因为std::less<int>永不成立。

(3)二进制关系,如果它对于元素及其本身始终保持,则称为自反,例如< ,因为a < a总是成立。

答案 2 :(得分:0)

将比较器包裹在交换参数顺序的地方。

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);
    // ...
}