There is an algorithm with time complexity similar to what you required, but it runs O(log n) only on average time, if it is what you needed. In this algorithm, you can use existing priority queue without the requeue() function.
Assuming you have a connection between the nodes in your graph and the elements in the priority queue. Let the element of the priority queue also store an extra bit called ignore. The algorithm for the modified dequeue runs as follow:
- Call
dequeue()
- If the
ignore bit in the element is true, go back to 1, otherwise return the item id.
The algorithm for the modified enqueue runs as follow:
- Call enqueue(item, priority)
- Visit neighbor nodes
v of the item in the graph one by one
- change the
ignore bit to true for the current linked element in the queue correspond to v
- enqueue(v, new_priority(v))
- change the connection of the node
v to the new enqueued elements.
num_ignore++
- If the number of ignore element (
num_ignore) is more than the number of non-ignore element, rebuild the priority queue
dequeue all elements, store, and then enqueue only non-ignore elements again
In this algorithm, the setting of ignore bit takes constant time, so you basically delay the O(log n) "requeue" until you accumulate O(n) ignore elements. Then clear all of them once, which takes O(n log n). Therefore, on average, each "requeue" takes O(log n).