I already know priority queues are implemented by default as max_priority queues in C++.
But how to make a min priority queue, rather than storing negetive of each number.
Please help , I am unable to find the syntax , and if able to find any syntax unable to use it and understand it :(.
http://www.cplusplus.com/reference/queue/priority_queue/
Use the constructor that allows you to pass your own compare object.
template < class T, class Container = vector,
class Compare = less > class priority_queue
Compare: Comparison class: A class such that the expression comp(a,b), where comp is an object of this class and a and b are elements of the container, returns true if a is to be placed earlier than b in a strict weak ordering operation. This can either be a class implementing a function call operator or a pointer to a function. This defaults to less, which returns the same as applying the less-than operator (a
Related
Does std::greater work when you have a std::pair of int and a class?
I am trying to create a priority queue of pairs, ordered by the first element:
std::priority_queue<std::pair<double, classA>, std::vector<std::pair<double, classA>>, std::greater<std::pair<double, classA>>> priorityQueue
But I get an error that says
no match for 'operator<'`
And it alludes to the second element of the std::pair, which is of class type.
Is std::greater applied to the first and second elements of the std::pair?
std::greater is just a wrapper for a call to operator < of the template type. For std::pair we can check the reference site here and we see it says
Compares lhs and rhs lexicographically by operator<, that is, compares the first elements and only if they are equivalent, compares the second elements.
So, it uses the operator < of both types, which means your class type needs to supply it. Since it doesn't you get the compiler error.
Your classA type needs to define an operator<.
Notice that std::pair compares lexicographically.
template <class T, class Container = vector<T>, class Compare = less<typename Container::value_type> > class priority_queue;
I understand the first two template arguments, the first template argument is the data type of the element being stored in the priority queue and the second one is the kind of container that the programmer wants to use, it could be either deque or vector.
But the third argument confuses me a bit, because I have never seen something like it. I'd have done something like:
template <class T, class Container = vector<T>
class priority_queue{
/* Implementation */
};
Does it have something to do with the strict weak ordering criterion necessary for priority queue? If yes, how can I learn more about it? Could you give an example of using the third argument?
I am new to template programming, so I'd really appreciate your help.
The third parameter specifies the comparator class.
The comparator class is responsible for comparing queue elements, in order to determine the queue order. You already understand that the elements in the queue are ordered with the "higher" values first. Well, this is what defines what "higher" means, here.
The comparator class has a simple interface: given two values, return true if the first value is less than the second value, and false otherwise. The default implementation, std::less, uses the traditional < operator to compare the two values.
Use a custom comparator class in order to change the behavior of the priority queue. One example would be to specify std::greater instead of std::less as the comparator class. std::greater uses the > operator, so this creates a priority queue "in opposite order", which gives you the lowest values first, rather than highest one.
Or, you could create your own custom comparator class, such as:
class last_four_bits {
public:
bool operator()(int a, int b) const
{
return (a & 0x0F) < (b & 0x0F);
}
};
This comparator class compares the least four bits of an int only. This, in turn, makes this:
std::priority_queue<int, std::vector<int>, last_four_bits>
look at the least four bits of each int value in the queue, thus ordering all ints with the highest values in the last four bits before the ones with the lesser values, ignoring all other bits in the int.
P.S. Comparator classes are also used with associative containers, sets and maps, and serve the same function there. By carefully crafting a comparator class you can create sets and maps whose iterators iterate over the keys in the set/map in some order other than the lowest to the highest keys (as you understand "lowest" and "highest" to mean, intrinsically).
In C++, the std::set::insert() only inserts a value if there is not already one with the same 'value'. By the same, does this mean operator== or does it mean one for which operator< is false for either ordering, or does it mean something else?
does it mean one for which operator< is false for either ordering?
Yes, if the set uses the default comparator and compares keys using <. More generally, in an ordered container with comparator Compare, two keys k1 and k2 are regarded as equivalent if !Compare(k1,k2) && !Compare(k2,k1).
Keys are not required to implement operator== or anything else; they are just required to be comparable using the container's comparator to give a strict weak ordering.
std::set has a template argument called `Compare' as in this signature:
template < class Key, class Compare = less<Key>,
class Allocator = allocator<Key> > class set;
Compare is used to determine the ordering between elements. Here, the default less<Key> uses the < operator to compare two keys.
If it helps, you can think of a set as just a std::map with meaningless values, ie a std::set<int> can be thought of as a std::map<int, int> where the values are meaningless.
The only comparison that set is allowed to perform on T is via the functor type it was given to do comparisons as part of the template. Thus, that's how it defines equivalence.
For every value in the set, the comparison must evaluate to true for one of the two ordering between that value and the new one. If it's false both ways for any value, then it won't be stored.
This is an interview question.
Referring to the sample code, which one of the operators needs to be overridden in order to use std::set<Value>
#include<iostream>
class Value
{
std::string s_val;
int i_val;
public:
Value(std::string s, int i): s_val(s) , i_val(i){}
};
// EOF
/*
a operator !=
b operator >
c operator <=
d operator >=
e operator <
*/
Actually, I do not understand why an operator needs to be overridden here. "set" does not allow duplicated elements, maybe operator != needs to be overridden ?
You don't have to override any operator, the std::set class template allows you to provide a comparison function as a template parameter. But if you were to provide an operator, the one needed is bool operator<(). This operator has to implement strict weak ordering. See this std::set documentation.
The reason strict weak ordering is used is because set is an ordered container, typically implemented as a self-balancing binary tree. So it is not enough to know whether two elements are the same or not. The set must be able to order them. And the less than operator or the comparator functor are also used to test for element equality.
You need to implement operator< for your type. The implementation must follow strick weak ordering to be able to use with associative containers from Standard library such as std::set and std::map.
Read about:
Strict Weak Ordering
An example here:
std map composite key
A set keeps out the duplicates without needing operator= or operator!= by using the notion of equivalence. Two items are equivalent if neither is less than the other:
if (!(a < b || b < a))
// equivalent!
To speed up the enforcement of no duplicate elements and generally checking if element is in its usually some sort of a tree and only needs operator <. (The only usage of less is enforced by the standard, the rest is just the avarage implementation)
From cplusplus.com:
template < class Key, class Compare = less<Key>,
class Allocator = allocator<Key> > class set;
"Compare: Comparison class: A class that takes two arguments of the same type as the container elements and returns a bool. The expression comp(a,b), where comp is an object of this comparison class and a and b are elements of the container, shall return true if a is to be placed at an earlier position than b in a strict weak ordering operation. This can either be a class implementing a function call operator or a pointer to a function (see constructor for an example). This defaults to less, which returns the same as applying the less-than operator (a<b).
The set object uses this expression to determine the position of the elements in the container. All elements in a set container are ordered following this rule at all times."
Given that the comparison class is used to decide which of the two objects is "smaller" or "less", how does the class check whether two elements are equal (e.g. to prevent insertion of the same element twice)?
I can imagine two approaches here: one would be calling (a == b) in the background, but not providing the option to override this comparison (as with the default less<Key>)doesn't seem too STL-ish to me. The other would be the assumption that (a == b) == !(a < b) && !(b < a) ; that is, two elements are considered equal if neither is "less" than the other, but somehow this doesn't feel right to me either, considering that the comparison can be an arbitrarily complex bool functor between objects of an arbitrarily complex class.
So how is it really done?
Not an exact duplicate, but the first answer here answers your question
Your second guess as to the behaviour is correct
Associative containers in the standard library are defined in terms of equivalence of keys, not equality per se.
As not all set and map instances use less, but may use a generic comparison operator it's necessary to define equivalence in terms of this one comparison function rather then attempting to introduce a separate equality concept.
In general, two keys (k1 and k2) in an associative container using a comparison function comp are equivalent if and only if:
comp( k1, k2 ) == false && comp( k2, k1 ) == false
In a container using std::less for types that don't have a specific std::less specialization, this means the same as:
!(k1 < k2) && !(k2 < k1)
Your mistake is the assumption that "the comparison can be an arbitrarily complex bool functor". It can't.
std::set requires a partial ordering so that a<b implies !(b<a). This excludes most binary boolean functors. Because of that, we can talk about the relative position of a and b in that ordering. If a<b, a precedes b. If b<a , b precedes a. If neither a<b nor b<a, then a and b occupy the same position in the ordering and thus are equivalent.
Your second option is the right one. Why doesn't feel it right? What would you do if the equality test wasn't consistent with the equation you give?