Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Operator overload or comparison function in C++ priority queue

I am writing a program in C++ and I would like to define priority queue of one of my class. I need it to compare objects by one of the class member variable. I have used an operator< overload, but I know there is a second way to achieve this goal - special function defined with queue definition. Which way is better, more esthetic and more efficient? And how to write such a function?

I have done it as follows:

#include <iostream>
#include <queue>
using namespace std;

class Human {

    public:
        string name;
        int age;
        Human(string name, int age);
};

Human::Human(string name, int age) : name(name), age(age) {}

bool operator<(Human a, Human b) {return a.age < b.age ? true : false;}

int main() {

    Human p1("Child",5);
    Human p2("Grandfather",70);
    Human p3("Older son",20);
    Human p4("Father",40);
    Human p5("Younger son",10); 

    priority_queue<Human> Q;

    Q.push(p1);
    Q.push(p2);
    Q.push(p3);
    Q.push(p4);
    Q.push(p5);

    while(!Q.empty()) {

        cout << "Name: " << Q.top().name << ", age: " << Q.top().age << endl;
        Q.pop();
    }
    return 0;
}
like image 327
Bartłomiej Szałach Avatar asked Dec 09 '12 18:12

Bartłomiej Szałach


People also ask

Can comparison operators be overloaded?

You can overload any of these operators, which can be used to compare the objects of a class. Following example explains how a < operator can be overloaded and similar way you can overload other relational operators.

Which operator is used in priority queue?

priority_queue pq; To rectify the above error we'll use operator overloading to define the priority, so that priority_queue can decide how to store the objects.

Can we use comparator function in priority queue C++?

You may have often come to a situation when you need to use a priority queue, but your datatype is something else that can't be compared by default (using '<' operator what is used by default). In such cases, we need to declare our comparator function. We can use the lambda function for that.

Can operator overloading change the precedence?

Overloading an operator cannot change its precedence.


3 Answers

The overloading of the operator is the best way because only performs a comparison instruction, nothing can be more performant, so your solution is optimal.

like image 185
HAL9000 Avatar answered Oct 12 '22 23:10

HAL9000


Style

If your type has an intrinsic, "natural" ordering, it is reasonable to express that with a built-in operator.

If the ordering varies by how you're using the type (eg. you have one collection of Human sorted by age, one by height, one by IQ), then it seems sensible to say the ordering is a property of the container instead of the type.


Implementation

You can write a free function, or use a functor if you need state.

Note that these are both exactly as amenable to inlining as a built-in operator, so there is no inherent difference in speed (it's probably harder for the compiler to prove a function pointer is inline-able though, so functors are generally preferred).

struct OrderByAge
{
    bool operator() (Human const &a, Human const &b) { return a.age < b.age; }
};
typedef std::priority_queue<Human, std::vector<Human>, OrderByAge> age_queue;
like image 40
Useless Avatar answered Oct 12 '22 23:10

Useless


#include <iostream>
#include <queue>
#include <iomanip>
#include <cstdlib>
using namespace std;

struct DatenWert {
    int ordnungsnummer;
};

class DaternWert_Compare {
public:
    bool operator()(DatenWert& t1, DatenWert& t2)
    {
       if (t1.ordnungsnummer < t2.ordnungsnummer) return true;
       return false;
    }
};

int main(int argc, char** argv) {

    priority_queue<DatenWert, vector<DatenWert>, DaternWert_Compare> pq;

    DatenWert wert2 = {2};
    DatenWert wert1 = {1};
    DatenWert wert3 = {3};

    pq.push(wert1);
    pq.push(wert2);
    pq.push(wert3);

    while (! pq.empty()) {
       DatenWert t2 = pq.top();
       cout << setw(3) << t2.ordnungsnummer << " " << setw(3) << endl;
       pq.pop();
    }

    return 0;
}

Result:

3 2 1

like image 36
Jonas_Hess Avatar answered Oct 13 '22 01:10

Jonas_Hess