1

I am working on a sorting function that uses a priority queue. The function is templated and takes in custom comparators:

template <class T, class Comparator>
void sort (std::vector<T>& myArray, Comparator comp) {}

The function creates a priority queue:

std::priority_queue<T, std::vector<T>, Comparator > pQueue;

Currently, top() and pop() returns and pops the highest value.

However, I am looking for a min priority queue that returns and pops the lowest value when using the top() and pop() functions. How should I go about doing this?

5
  • 2
    Change the return of the comparator to its negative? (using !) Commented Oct 23, 2018 at 13:30
  • Unfortunately the comparator cannot be changed Commented Oct 23, 2018 at 13:35
  • Why? You want a priority queue with low instead of high, then use the opposite comparator, and that's it. Commented Oct 23, 2018 at 13:36
  • The test cases I am running it against have comparators which cannot be altered Commented Oct 23, 2018 at 13:41
  • What are you trying to achieve by making pop() and top() not the way it is supposed to behave for the given comparator? Commented Mar 17, 2019 at 15:38

3 Answers 3

3

Just swap the arguments given to your Comparator object:

auto cmp = [](auto a, auto b) { return Comparator()(b, a); };
std::priority_queue<int, std::vector<int>, decltype(cmp)> pq(cmp);

Note that your Comparator (i.e., the Compare in std::priority_queue) must provide strict weak ordering.

A Compare type providing a strict weak ordering.

However, the lambda expression

auto cmp = [](auto a, auto b) { return !Comparator()(a, b); };

may not provide a strict weak ordering. For example, if Comparator()(a, b) is defined to be a < b, then !Comparator()(a, b) would be equivalent to !(a < b), which is in turn equivalent to a >= b and definitely different from a > b.

Unlike the > operator, the >= operator is a binary relation1 that does not provide strict weak ordering because strictness2 does not hold, since it is true that a >= a, i.e., it is actually reflexive3.


(1) A binary relation is just a binary predicate, i.e., a boolean function taking two parameters, e.g., the relational operators or the operator() member function of std::less<int>.

(2) A binary relation it is said to be strict, if it never holds for an element and itself, e.g., <, since a < a never holds.

(3) A binary relation it is said to be reflexive, if it always holds for an element and itself, e.g., <=, since a <= a always holds.

Sign up to request clarification or add additional context in comments.

Comments

2

std::priority_queue is a max-heap (by default) and only the largest element is available. If you want it to be a min-heap then you need to reverse the sorting condition. So, if comp(a, b) would return true if a < b then we need to swap a and b to turn the std::priority_queue into a min-heap. That would look like

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

Comments

0

Wrap the comparator in something that swaps the order of parameters.

a < b is exactly equal to 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);
    // ...
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.