简体   繁体   中英

How do you update values in priority_queue, or is there another way to update keys in heaps in c++

I was going through Djikstra's algorithm when I noticed, I could update keys in heap(with n keys) in O(logn) time (last line in the pseudocode ). How do I update keys in heaps in C++, is there any method in priority_queues to do this? Or do I have to write my own heap class to do achieve updates in O(logn) like this?

Edit 1:
Clarifying my need - for a binary heap with n elements -
1) Should insert new values and find & pop minimum values in O(logn)
2) Should update already present keys in O(logn)

I tried to come up with a way to implement this using make_heap, push_heap, pop_heap, and a custom function for update as John Ding suggested.

However I am facing a problem in making the function, I first need to find the location of the key in the heap. Doing this under O(logn) in a heap requires a lookup array for position of keys in heap, see here (I don't know of any other way). However these lookup tables won't be updated when I call push_heap or pop_heap.

You can optimize dijktra algorithm with priority_queue . It is implemented by a binary heap , where you can pop the top or push in a element in O(logN) time. However, due to the encapsulation of priority_queue , you cannot modify the key(more pricisely, decrease the key) of any element.

So our method is to push multiple elements into the heap regardless of whether we have multiple elements refering to the same node.

for example, when

Node N : distance = 30, GraphNode = A (where A refers to one node in the graph, while N is one node in the heap)

is already in the heap, then using the priority_queue cannot help you do such a operation when we try to relax Node N:

decrease_key_to(N, 20)

by decreasing key can make the heap always include less than N elements, but it's cannot be implemented by priority_queue

What we can do with it is to add another node in the heap:

Node N2 : distance = 20, GraphNode = A
push N2 into the heap

That's corresponding to priority_queue::push

So you may need to implement a binary heap supporting decrease_key yourself or find an implementation online, and store a table of pointers pointing to every element in a heap to know access elements through nodes in the graph.

As an extension, using Fibonacci heap can even make decrease_key faster, that's the ultimate level of Dijkstra, Haha :)


Problem of last version of my answer:

We cannot locate the element pushed in to the heap using push_heap .

In order to do this, you need more than the priority_queue provides: you need to know where in the underlying container the element to be updated is stored. In a binary heap, for example, you need to know the position of the element for which you want to change the priority. With this you can change the priority of the element and then restore the heap property in O(log n) by bubbling the modified element up or down.

For Dijkstra, if I remember correctly, something called Fibonacci heap is more efficient than a binary heap.

Unfortunately, std::priority_queue doesn't support updates of entries in the heap, but you may be able to invalidate entries in the heap and wait for them to percolate up to the root from where they can eventually be deleted. So instead of changing an existing entry, you invalidate it and insert another one with the new priority. Whether you can live with the consequences of having invalid entries filling up the heap, is for you to judge.

For an idea how this might work in practice, see here .

我用 C++ 编写了一个没有库的程序: https ://github.com/NTC09/Mini-Project-Test/blob/main/Heap_index.cpp

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