1

Following code uses same comparator function with vector and priority queue. However order produced by both data structures is different. I would like priority queue to behave in same way as vector.

I have two questions

  1. Why is order different?
  2. How can i make priority queue's order to be same as vector?

Here's the output of following code:

enter image description here

//Please ignore extra header files, I know I don't need them.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>
#include <stack>
#include <iterator>
#include <unordered_map>
#include <functional>

using namespace std;

class Solution {
public:
    typedef pair<string, int> PII;
    static bool cmp(const PII& a, const PII& b)
    {
        if (a.second == b.second)
            return a.first < b.first;
        return a.second > b.second;
    }
    void func(vector<string>& words)
    {
        unordered_map<string, int> hMap;
        for (const auto& w : words)
            hMap[w]++;
        std::priority_queue< PII, std::vector<PII>, std::function<bool(PII, PII)> > Q(cmp);
        vector<PII> V;
        for (const auto& e : hMap)
        {
            Q.emplace(e);
            V.emplace_back(e);
        }
        std::sort(V.begin(), V.end(), cmp);

        //Now why does order of elements is different in vector V and priority_queue Q, despite using same comparator function?
        int size = Q.size();
        cout << "Order in priority Queue:" << endl;
        for (int i = 0; i < size; i++)
        {
            PII e = Q.top();
            cout << e.first << ":" << e.second << endl;
            Q.pop();
        }

        cout << "Order in vector:" << endl;
        for (const auto& e : V)
        {
            cout << e.first << ":" << e.second << endl;
        }
    }
};

int main()
{
    Solution s;
    vector<string> words = {"the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is" , "we" , "we" , "we" };
    s.func( words );
    return 0;
}
E.N.D
  • 1,151
  • 5
  • 10
  • Quote from [cpreference](https://en.cppreference.com/w/cpp/container/priority_queue) "Note that the Compare parameter is defined such that it returns true if its first argument comes before its second argument in a weak ordering. But because the priority queue outputs largest elements first, the elements that "come before" are actually output last." – Yksisarvinen Apr 29 '20 at 08:17
  • @Evg Why is it being closed as duplicate? I know how to use comparator for min heaps. This question is about the way comparator is interpreted by both data structures. – E.N.D Apr 29 '20 at 08:19

2 Answers2

0

The order is different because < relation implies that std::sort sorts values in ascending order, and that std::priority_queue places the maximum element at the top. This is by design.

If you want to reverse the order in the priority queue, you need another comparator that swaps the arguments,

bool cmp2(const T& a, const T& b) {
    return cmp(b, a);
}

//...
std::priority_queue<T, std::vector<T>, decltype(&cmp2)> queue(cmp2);

This is in perfect analogy with going from std::less to std::greater as explained in this question.

Instead of introducing a separate function, you can use a lambda:

auto cmp2 = [](const auto& a, const auto& b) { return cmp(b, a); };
std::priority_queue<T, std::vector<T>, decltype(cmp2)> queue(cmp2);
Evg
  • 20,870
  • 4
  • 34
  • 69
0

Priority Queues and vectors use comparators differently. To understand the output of priority queue, you must understand its working. Priority Queue is effectively a heap with an element on top depending on the comparison function. To quote from boost Priority Queue

The comparison function used to determine whether one element is smaller than another element. If Compare(x,y) is true, then x is smaller than y. The element returned by Q.top() is the largest element in the priority queue. That is, it has the property that, for every other element x in the priority queue, Compare(Q.top(), x) is false.

In your case changing the comparison function to reverse the order should solve the issue.

Bugman
  • 191
  • 6