Module 0x2::priority_queue
Priority queue implemented using a max heap.
- Struct
PriorityQueue
- Struct
Entry
- Constants
- Function
new
- Function
pop_max
- Function
insert
- Function
new_entry
- Function
create_entries
- Function
restore_heap_recursive
- Function
max_heapify_recursive
- Function
priorities
use 0x1::vector;
Struct PriorityQueue
Struct representing a priority queue. The entries
vector represents a max
heap structure, where entries[0] is the root, entries[1] and entries[2] are the
left child and right child of the root, etc. More generally, the children of
entries[i] are at i * 2 + 1 and i * 2 + 2. The max heap should have the invariant
that the parent node's priority is always higher than its child nodes' priorities.
struct PriorityQueue<T: drop> has drop, store
Fields
entries: vector<priority_queue::Entry<T>>
Struct Entry
struct Entry<T: drop> has drop, store
Fields
priority: u64
value: T
Constants
For when heap is empty and there's no data to pop.
const EPopFromEmptyHeap: u64 = 0;
Function new
Create a new priority queue from the input entry vectors.
public fun new<T: drop>(entries: vector<priority_queue::Entry<T>>): priority_queue::PriorityQueue<T>
Implementation
public fun new<T: drop>(mut entries: vector<Entry<T>>) : PriorityQueue<T> {
let len = entries.length();
let mut i = len / 2;
// Max heapify from the first node that is a parent (node at len / 2).
while (i > 0) {
i = i - 1;
max_heapify_recursive(&mut entries, len, i);
};
PriorityQueue { entries }
}
Function pop_max
Pop the entry with the highest priority value.
public fun pop_max<T: drop>(pq: &mut priority_queue::PriorityQueue<T>): (u64, T)
Implementation
public fun pop_max<T: drop>(pq: &mut PriorityQueue<T>) : (u64, T) {
let len = pq.entries.length();
assert!(len > 0, EPopFromEmptyHeap);
// Swap the max element with the last element in the entries and remove the max element.
let Entry { priority, value } = pq.entries.swap_remove(0);
// Now the max heap property has been violated at the root node, but nowhere else
// so we call max heapify on the root node.
max_heapify_recursive(&mut pq.entries, len - 1, 0);
(priority, value)
}
Function insert
Insert a new entry into the queue.
public fun insert<T: drop>(pq: &mut priority_queue::PriorityQueue<T>, priority: u64, value: T)
Implementation
public fun insert<T: drop>(pq: &mut PriorityQueue<T>, priority: u64, value: T) {
pq.entries.push_back(Entry { priority, value});
let index = pq.entries.length() - 1;
restore_heap_recursive(&mut pq.entries, index);
}
Function new_entry
public fun new_entry<T: drop>(priority: u64, value: T): priority_queue::Entry<T>
Implementation
Function create_entries
public fun create_entries<T: drop>(p: vector<u64>, v: vector<T>): vector<priority_queue::Entry<T>>
Implementation
public fun create_entries<T: drop>(mut p: vector<u64>, mut v: vector<T>): vector<Entry<T>> {
let len = p.length();
assert!(v.length() == len, 0);
let mut res = vector[];
let mut i = 0;
while (i < len) {
let priority = p.remove(0);
let value = v.remove(0);
res.push_back(Entry { priority, value });
i = i + 1;
};
res
}
Function restore_heap_recursive
fun restore_heap_recursive<T: drop>(v: &mut vector<priority_queue::Entry<T>>, i: u64)
Implementation
fun restore_heap_recursive<T: drop>(v: &mut vector<Entry<T>>, i: u64) {
if (i == 0) {
return
};
let parent = (i - 1) / 2;
// If new elem is greater than its parent, swap them and recursively
// do the restoration upwards.
if (*&v[i].priority > *&v[parent].priority) {
v.swap(i, parent);
restore_heap_recursive(v, parent);
}
}
Function max_heapify_recursive
Max heapify the subtree whose root is at index i
. That means after this function
finishes, the subtree should have the property that the parent node has higher priority
than both child nodes.
This function assumes that all the other nodes in the subtree (nodes other than the root)
do satisfy the max heap property.
fun max_heapify_recursive<T: drop>(v: &mut vector<priority_queue::Entry<T>>, len: u64, i: u64)
Implementation
fun max_heapify_recursive<T: drop>(v: &mut vector<Entry<T>>, len: u64, i: u64) {
if (len == 0) {
return
};
assert!(i < len, 1);
let left = i * 2 + 1;
let right = left + 1;
let mut max = i;
// Find the node with highest priority among node i
and its two children.
if (left < len && *&v[left].priority > *&v[max].priority) {
max = left;
};
if (right < len && *&v[right].priority > *&v[max].priority) {
max = right;
};
// If the parent node (node i
) doesn't have the highest priority, we swap the parent with the
// max priority node.
if (max != i) {
v.swap(max, i);
// After the swap, we have restored the property at node i
but now the max heap property
// may be violated at node max
since this node now has a new value. So we need to now
// max heapify the subtree rooted at node max
.
max_heapify_recursive(v, len, max);
}
}
Function priorities
public fun priorities<T: drop>(pq: &priority_queue::PriorityQueue<T>): vector<u64>
Implementation
public fun priorities<T: drop>(pq: &PriorityQueue<T>): vector<u64> {
let mut res = vector[];
let mut i = 0;
while (i < pq.entries.length()) {
res.push_back(pq.entries[i].priority);
i = i +1;
};
res
}