Search code examples
c++priority-queue

Create priority_queue using struct and map


I have struct:

struct Node {
    unsigned char symbol;
    unsigned int freq;
    Node* left;
    Node* right;

    Node(unsigned char _byte, int _freq)
        : symbol(_byte), freq(_freq), left(nullptr), right(nullptr) {};
};

and already created such unordered_map:

std::unordered_map<unsigned char, uint> freqs ={{'a',12}, {'b',122}};

What I want to do - is to create priority_queue the next way:

  1. Create new Node for every pair from freqs
  2. Create priority_queue from all of this Nodes.

What I tried so far: create vector from map and try to create priority_queue:

bool nodeCompare(const Node* first, const Node* second){
    return first->freq > second->freq;
}

typedef std::priority_queue<Node*,
                            std::vector<Node*>,
                            nodeCompare()> my_queue;

std::vector<Node*> node_vect;
std::unordered_map<byte, uint>::iterator it;
for (it = freqs.begin(); it != freqs.end(); ++it)
{
    Node* new_node = new Node(it->first, it->second);
    node_vect.push_back(new_node);
}
my_queue(node_vect.begin(), node_vect.end(), nodeCompare);

But this doesn't work: error in typedef construction:

function "nodeCompare" is not a type name

Additional question: if I create my vector in this way, maybe there is some method to push Nodes into my_queue without creating additional vector?

my_queue q;
std::vector<Node*> node_vect;
std::unordered_map<byte, uint>::iterator it;
for (it = freqs.begin(); it != freqs.end(); ++it)
{
    Node* new_node = new Node(it->first, it->second);
    node_vect.push_back(new_node);
    //q.push(new_node); this doesn't work
}

Solution

  • priority_queue template parameter doesn't expect a function but instead an object Type

    template <class T, class Container = vector<T>,
      class Compare = less<typename Container::value_type> > class priority_queue;
    

    so just wrap that function into a struct/class (Functor) and that should work.

    struct Comparator
    {
      bool operator()(const Node* first, const Node* second) const {
        return first->freq > second->freq;
      }
    };
    
    typedef std::priority_queue<Node*,
                                std::vector<Node*>,
                                Comparator> my_queue;
    

    If you want the Comparator inside the Node struct just make an inner struct

    struct Node {
        unsigned char symbol;
        unsigned int freq;
        Node* left;
        Node* right;
    
        Node(unsigned char _byte, int _freq)
            : symbol(_byte), freq(_freq), left(nullptr), right(nullptr) {};
    
        struct Comparator
        {
          bool operator()(const Node* first, const Node* second) const {
            return first->freq > second->freq;
          }
        };
    };
    
    typedef std::priority_queue<Node*,
                                std::vector<Node*>,
                                Node::Comparator> my_queue;
    
    my_queue queue(node_vect.begin(), node_vect.end());