Reputation: 2595
I have a priority_queue
that contains a vector
with some objects.
std::priority_queue<std::shared_ptr<Foo>, std::vector<std::shared_ptr<Foo>>, foo_less> foo_queue;
It has a foo_queue
function that will order the priority_queue
.
Now, from outside of the priority_queue
, I want to change some object value that must influenciate the ordering of the priority_queue
.
My question is:
How can I set some kind of "refresh" that will trigger the priority_queue
to run the foo_queue()
in order to keep it orderes all the time?
Upvotes: 2
Views: 365
Reputation: 15501
Make your own priority queue using the standard heap algorithms and a vector. When you want to change a key, find and remove that value from the underlying vector and call make_heap on the vector. Alter the key and then push it back onto the heap. So the cost is a linear search of the vector to find the value and a call to make_heap (which I think is also linear).
#include <iostream>
#include <vector>
#include <algorithm>
template <class T, class Container = std::vector<T>,
class Compare = std::less<T> >
class my_priority_queue {
protected:
Container c;
Compare comp;
public:
explicit my_priority_queue(const Container& c_ = Container(),
const Compare& comp_ = Compare())
: c(c_), comp(comp_)
{
std::make_heap(c.begin(), c.end(), comp);
}
bool empty() const { return c.empty(); }
std::size_t size() const { return c.size(); }
const T& top() const { return c.front(); }
void push(const T& x)
{
c.push_back(x);
std::push_heap(c.begin(), c.end(), comp);
}
void pop()
{
std::pop_heap(c.begin(), c.end(), comp);
c.pop_back();
}
void remove(const T& x)
{
auto it = std::find(c.begin(), c.end(), x);
if (it != c.end()) {
c.erase(it);
std::make_heap(c.begin(), c.end(), comp);
}
}
};
class Foo {
int x_;
public:
Foo(int x) : x_(x) {}
bool operator<(const Foo& f) const { return x_ < f.x_; }
bool operator==(const Foo& f) const { return x_ == f.x_; }
int get() const { return x_; }
void set(int x) { x_ = x; }
};
int main() {
my_priority_queue<Foo> q;
for (auto x: {7, 1, 9, 5}) q.push(Foo(x));
while (!q.empty()) {
std::cout << q.top().get() << '\n';
q.pop();
}
std::cout << '\n';
for (auto x: {7, 1, 9, 5}) q.push(Foo(x));
Foo x = Foo(5);
q.remove(x);
x.set(8);
q.push(x);
while (!q.empty()) {
std::cout << q.top().get() << '\n';
q.pop();
}
}
Upvotes: 1