简体   繁体   中英

Mutable priority queue allowing key increase

When implementing a graph search algorithm, I needed a priority queue which allowed for priority changes. Until now, I've been using the ( detail namespaced, so undocumented) boost d_ary_heap_indirect , but was just told it is undefined to have priorities increase (which I see now is also mentioned in the concept documentation ).

So, I need to find a structure which allows both increase and decrease. I've already tried simply using a vector and push_heap / pop_heap / make_heap , but updates are too slow. What are the alternatives? I see boost has two classes in the pending (again, undocumented) directories, mutable_queue and relaxed_heap , but I can only find mention of them on five year old maillist threads. What are the differences between them, and do they allow both increases and decreases? Are there any implementations which are not pending acceptance?

Put the value in a heap. All you need to do is modify the value, then restore the heap invariant by either bubbling up or down the value.

Recall that a heap is essentially a binary tree where each node is larger than both of its child nodes.

So if you increase the value of a node, you check if it has become greater than its parent and if so swap them, then repeat pulling the node toward the trees root until the node no longer needs to be swapped.

if you decrease the value of a node then if you are now smaller than the largest of your two children swap. Repeat pushing the node towards the trees leaves until you no longer need to swap.

The Boost.MultiIndex library features container that have operations to update the state of the object and will accordingly update the indexes.

In your case, the modify member function seems to fit. From the documentation:

struct change_name
{
  change_name(const std::string& new_name):new_name(new_name){}

  void operator()(employee& e)
  {
    e.name=new_name;
  }

private:
  std::string new_name;
};

typedef employee_set::index<name>::type employee_set_by_name;
employee_set_by_name& name_index = es.get<name>();

employee_set_by_name::iterator it = name_index.find("Anna Jones");
name_index.modify(it,change_name("Anna Smith"));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM