How to remove element not at top from priority_queue?
In my program I need to delete an element from a priority queue that is not at the top. Can that be done? If not, please suggest a way to do so except creating your own heap.
The standard priority_queue<T>
can be customized through inheritance. It has protected members c
and comp
that can be referenced in a descendant class.
template<typename T>
class custom_priority_queue : public std::priority_queue<T, std::vector<T>>
{
public:
bool remove(const T& value) {
auto it = std::find(this->c.begin(), this->c.end(), value);
if (it != this->c.end()) {
this->c.erase(it);
std::make_heap(this->c.begin(), this->c.end(), this->comp);
return true;
}
else {
return false;
}
}
};
void main()
{
custom_priority_queue<int> queue;
queue.push(10);
queue.push(2);
queue.push(4);
queue.push(6);
queue.push(3);
queue.remove(6);
while (!queue.empty())
{
std::cout << queue.top();
queue.pop();
if (!queue.empty())
{
std::cout << ", ";
}
}
}
Output:
10, 4, 3, 2
The best solution is to use std::set. Sets provide methods which allow it to be used both as a min/max heap (or a priority queue).
std::set<int> pq;
//accessing the smallest element(use as min heap)
*pq.begin();
//accessing the largest element (use as max heap)
*pq.rbegin();
Furthermore sets also allow random deletion.
//to delete the integer '6'
auto it = pq.find(6);
pq.erase(it);
A neat little trick to handle deletes for a priority_queue STL - use another priority_queue, say, del_pq
. Keep inserting all the delete values to this. When you are popping values from the original priority queue, check with top of del_pq
and see if we wanted to delete it. If it matches, delete the value from the original priority_queue.
This method implements a way to lazily delete the values in our original priority queue. Can take up twice the memory, but average delete and inserts remain O(logN)
.