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;
}
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.
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.
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.
Overloading an operator cannot change its precedence.
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.
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.
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;
#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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With