How to use different comparators for priority queue depending on conditions

I'm working on an assignment where I have a priority queue and I want it to work like this:

if(field == '0')
    priority_queue<record_t*,vector<record_t*>, CompareRecordID > pq;
else if(field == '1')
    priority_queue<record_t*,vector<record_t*>, CompareRecordNum > pq;
else if(field == '2')
    priority_queue<record_t*,vector<record_t*>, CompareRecordStr > pq;
else if(field == '3')
    priority_queue<record_t*,vector<record_t*>, CompareRecordNumStr > pq;

      

Where record_t is:

typedef struct {
   unsigned int recid;
   unsigned int num;
   char str[STR_LENGTH];
   bool valid;  // if set, then this record is valid
   int blockID; //The block the record belongs too -> Used only for minheap
} record_t;

      

This means that depending on the function argument field, the queue will "sort" another record_t field. However, I cannot declare the queue inside the if statement, as this will obviously give me a "pq was not declared in this scope" error. What can I do?

+3


source to share


2 answers


You can use a constructor std::priority_queue

that takes a comparator object as a parameter. Then you can copy its configurable comparator a little like this:

#include <vector>
#include <queue>
#include <cstring>
#include <iostream>

const int STR_LENGTH = 20;

struct record_t
{
   unsigned int recid;
   unsigned int num;
   char str[STR_LENGTH];
   bool valid;  // if set, then this record is valid
   int blockID; //The block the record belongs too -> Used only for minheap
};

// switchable priority comparator
struct CompareRecord
{
    int field;

    CompareRecord(int field = 0): field(field) {}

    bool operator() (const record_t* lhs, const record_t* rhs) const
    {
        switch(field)
        {
            case 0: return lhs->recid < rhs->recid;
            case 1: return lhs->num < rhs->num;
            case 2: return std::strcmp(lhs->str, rhs->str) < 0;
        }
        return true;
    }
};

int main()
{
    // physical records
    std::vector<record_t> records;

    record_t r;

    r.recid = 1;
    r.num = 1;
    std::strcpy(r.str, "banana");

    records.push_back(r);

    r.recid = 2;
    r.num = 4;
    std::strcpy(r.str, "orange");

    records.push_back(r);

    r.recid = 3;
    r.num = 2;
    std::strcpy(r.str, "apple");

    records.push_back(r);

    // input priority type: 0, 1 or 2

    int field;

    std::cout << "Sort type [0, 1, 2]: " << std::flush;
    std::cin >> field;
    std::cout << '\n';

    // build priority view

    CompareRecord cmp(field);
    std::priority_queue<record_t*, std::vector<record_t*>, CompareRecord> pq(cmp);

    for(auto& r: records)
        pq.push(&r);

    while(!pq.empty())
    {
        std::cout << "rec: " << pq.top()->recid << '\n';
        std::cout << "num: " << pq.top()->num << '\n';
        std::cout << "str: " << pq.top()->str << '\n';
        std::cout << '\n';
        pq.pop();
    }
}

      



Output:

Sort type [0, 1, 2]: 0

rec: 3
num: 2
str: apple

rec: 2
num: 4
str: orange

rec: 1
num: 1
str: banana

      

+2


source


The priority_queue value can take a comparator as a constructor argument.

std::priority_queue<record_t*,vector<record_t*>, CompareRecord > pq((CompareRecord(field)));

      

You just need to define the CompareRecord comparator appropriately. An easy way to do this would be:



struct CompareRecord{
   char type;
   CompareRecord(char type):type(type){}
   bool operator()(const record_t* lhs, const record_t* rhs){
     switch(type){
        case '1': return lhs->recid < rhs->recid;
.. and so forth.

   }

      

}

+1


source







All Articles