Why priority queue have that signature ?
std::priority_queue<int, std::vector<int>, std::greater<int> > third;
For what need std::vector<int>? If I, for example, need to store in queue only ints ?
These are the template arguments for priority_queue. The second one is the backing container used for storing the values and in this case you use vector (which is the default container). In the example above it is passed so that you can change the default comparison predicate with std::greater(i.e. have a priority_queue where the smallest value is at the top). Have a look at the class declaration here.
Related
Whenever I want to create a min-heap using a priority queue (which creates a max-heap by default),
I need to pass a comparator and also a vector of the required type to be sorted, something like this:
std::priority_queue<int, std::vector<int>, std::greater<int> > pq;
Why do we do this? And why do we not have to the same for a max-heap implementation?
Because of template parameters being positional and C++ standard commitee's decision to order the containter type before the comparator type.
Just like with a function like this:
void foo(int a = 1, int b = 2);
- you can't call it specifying b, but not a.
For max-heap, you're using std::less<int>, which happens to be the default, therefore you can omit the container type as well.
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).
I was looking through some STL documentation. I see that the syntax for a priority queue which stores in a descending order is:
std::priority_queue<int> q ;
//gives 9 8 7 6 5 4 3 2 1 when pushed and obtained
However, for storing in an ascending fashion, it's:
std::priority_queue< int, std::vector<int>, std::greater<int> > q ;
//gives 1 2 3 4 5 6 7 8 9 when pushed and obtained
I want to know what are the specific uses of the extra template parameters in the second example. As in, what does std::vector<int> do in that example?
Also, can someone could further explain this declaration?
priority_queue< pair<int ,int > , vector< pair<int ,int > > , greater< pair<int ,int > > > q ;
std::priority_queue is not a container in itself, it's a container adaptor, which means it uses another container internally to store the actual data in the queue.
By default it uses a std::vector of the type stored in the queue.
The problem here is that just like passing arguments to a function with default arguments, you can't skip arguments in the template list even if they have default types, you must always provide the previous template arguments.
If you see the linked reference you will see that the second and third template arguments to std::priority_queue have default types. If you want to change the third template argument you must also provide the second template argument as well, which is the actual underlying container. So for a std::priority_queue of int, you need to provide std::vector<int>.
There are however a way to not pass the type of the comparator as a template argument, the std::priority_queue constructor also takes an (optional) argument for the comparator function. Here you can provide any function, function object, lambda or other callable object.
In your case you could do e.g.
std::priority_queue<int> q{std::greater<int>()};
The above declaration creates a std::greater<int> object and passes it as comparator to the std::priority_queue constructor.
template<
class T,
class Container = std::vector<T>,
class Compare = std::less<typename Container::value_type>
> class priority_queue;
std::priority_queue is a container which wraps another container, meaning that it only provide priority and queue abstraction on top of another container, as long this one match the SequenceContainer concept.
A user may change containers if it want different time and memory complexity constraint. Or provide its own container.
the std::greater<T> is a comparator on elements of type T. It is required to satisfy total ordering.
To construct a priority_queue in c++
priority_queue<int, vector<int>, greater<int> > pq
int is the type of value the queue stores, greater is the comparator what does the second argument
vector<int>
do here?
The second parameter is the underlying container that the queue uses.
The priority_queue template is a container adaptor. That is, it doesn't provide dynamic storage itself, but rather, it adapts an existing container to provide the desired interface.
(The interface for a priority queue is implemented in terms of the make_heap/push_heap/pop_heap algorithms from the standard library, and the underlying container needs to have suitable iterators.)
I have a problem with stl priority queue.I want to have the priority queue in the increasing
order,which is decreasing by default.Is there any way to do this in priority queue.
And what is the complexity of building stl priority queue.If i use quick sort in an array which takes O(nlgn) is its complexity is similar to using priority queue???
Plz someone ans.Advanced thanx.
priority_queue has template parameters that specify the container type and the comparison to use for ordering. By default, the comparison is less<T>; to get the opposite ordering, use priority_queue<T, vector<T>, greater<T>>.
Insertion into a priority queue takes logarithmic time, so building a queue of N items has complexity O(N logN), the same as building and sorting a vector. But once it's built, insertion into the priority queue is still logarithmic, while insertion into a sorted vector is linear.
Use the type
priority_queue<T, vector<T>, greater<T> >
Use a different comparator as the 3rd template argument of std::priority_queue.
priority_queue is a container adaptor that works on any sequence you define. The performance of insertion is equal to the std::push_heap operation and takes logarithmic time. So the complexity to sorting after all insertions are done isn't equal. If you insert a fixed amount and work the queue afterwards a vector and a single sort could be more efficient.
You can just push values multiplying them by -1 so it will be stored in reverse order unlike the actual default order...and multiply the value with -1 again while retrieving data to get it in its actual form.
Replace T bellow with variable type. You will get your work done
priority_queue<T, vector<T>, greater<T> > PQ;
As example for int type variable you can write it like this:
priority_queue<int, vector<int>, greater<int> > Q;
You can use comparator class/struct to achieve the same in priority queue.
class CompareHeight
{
public:
bool operator()(int &p1, int &p2)
{
return p1 > p2;
}
};
Now declare the priority queue as
priority_queue<int, vector<int>, CompareHeight> pq;