moonbitstack/moonstl/heap does not have a README file

    DaryHeap

    pub struct DaryHeap[T] {
    arity : Int
    cmp : (T, T) -> Int
    items : Array[T]
    } derive(
    Debug
    )

    A d-ary heap: a heap laid out in a contiguous array where every node has up to arity children.

    A binary heap does one comparison per level; a 4-ary heap does three but halves the number of levels, and the children of one node sit next to each other in memory, so a wider heap usually wins on modern caches. arity: 4 is Boost.Heap's default for d_ary_heap.

    The heap is a multiset: it does not remove duplicates, and its iteration order is the internal array order, which is only partially ordered. Use into_sorted_array when the order matters.

    test {
    let heap : @heap.DaryHeap[Int32] = try! @heap.DaryHeap::new()
    heap.push(3)
    heap.push(1)
    heap.push(2)
    assert_true(heap.peek() == Some(1))
    assert_true(heap.pop() == Some(1))
    assert_true(heap.length() == 2)
    }
    impl Default for DaryHeap[T]
    impl Eq for DaryHeap[T]
    impl Hash for DaryHeap[T]
    impl Show for DaryHeap[T]

    DaryHeap::clear

    fn[T] DaryHeap::clear(self : DaryHeap[T]) -> Unit

    Removes every element.

    DaryHeap::copy

    fn[T] DaryHeap::copy(self : DaryHeap[T]) -> DaryHeap[T]

    A copy that shares no storage with the original; the comparator is shared because it is a pure function of two elements.

    DaryHeap::default

    fn[T : Compare + Eq] DaryHeap::default() -> DaryHeap[T]

    DaryHeap::equal

    fn[T : Eq] DaryHeap::equal(self : DaryHeap[T], other : DaryHeap[T]) -> Bool

    DaryHeap::from_array

    fn[T : Compare + Eq] DaryHeap::from_array(items : ArrayView[T], arity? : Int, order? : Order) -> DaryHeap[T] raise
    Refused

    Builds a heap from items in O(n), by sifting down from the last parent rather than pushing one at a time.

    test {
    let heap : @heap.DaryHeap[Int32] = try! @heap.DaryHeap::from_array([
    5, 1, 4, 1, 3,
    ])
    assert_true(heap.into_sorted_array() == [1, 1, 3, 4, 5])
    }

    DaryHeap::from_array_by

    fn[T] DaryHeap::from_array_by(items : ArrayView[T], cmp~ : (T, T) -> Int, arity? : Int) -> DaryHeap[T] raise
    Refused

    Builds a heap ordered by cmp from items in O(n).

    DaryHeap::from_iter

    fn[T : Compare + Eq] DaryHeap::from_iter(iter : Iter[T], arity? : Int, order? : Order) -> DaryHeap[T] raise
    Refused

    Builds a heap from an iterator in O(n log n).

    DaryHeap::from_iter_by

    fn[T] DaryHeap::from_iter_by(iter : Iter[T], cmp~ : (T, T) -> Int, arity? : Int) -> DaryHeap[T] raise
    Refused

    Builds a heap ordered by cmp from an iterator.

    DaryHeap::hash

    fn[T : Hash] DaryHeap::hash(self : DaryHeap[T]) -> Int

    DaryHeap::hash_combine

    fn[T : Hash] DaryHeap::hash_combine(self : DaryHeap[T], hasher : Hasher) -> Unit

    DaryHeap::into_sorted_array

    fn[T] DaryHeap::into_sorted_array(self : DaryHeap[T]) -> Array[T]

    Drains the heap into an array in pop order, leaving it empty.

    test {
    let heap : @heap.DaryHeap[Int32] = try! @heap.DaryHeap::from_array([3, 1, 2])
    assert_true(heap.into_sorted_array() == [1, 2, 3])
    assert_true(heap.is_empty())
    }

    DaryHeap::is_empty

    fn[T] DaryHeap::is_empty(self : DaryHeap[T]) -> Bool

    Whether the heap holds no elements.

    DaryHeap::iter

    fn[T] DaryHeap::iter(self : DaryHeap[T]) -> Iter[T]

    The elements in the heap's internal array order, which is only partially ordered.

    DaryHeap::length

    fn[T] DaryHeap::length(self : DaryHeap[T]) -> Int

    The number of elements the heap holds.

    DaryHeap::new

    fn[T : Compare + Eq] DaryHeap::new(arity? : Int, order? : Order) -> DaryHeap[T] raise
    Refused

    Builds a min or max heap ordered by T : Compare.

    arity is the number of children a node has and has to be at least 2; anything smaller is refused because it does not describe a tree.

    DaryHeap::new_by

    fn[T] DaryHeap::new_by(cmp~ : (T, T) -> Int, arity? : Int) -> DaryHeap[T] raise
    Refused

    Builds a min heap ordered by cmp, which has to return a negative number when its first argument has to be popped first.

    Use this for an ordering Compare cannot express — a case-insensitive key, a field of a record, a reversed priority — rather than wrapping the element.

    DaryHeap::not_equal

    fn[T : Eq] DaryHeap::not_equal(x : DaryHeap[T], y : DaryHeap[T]) -> Bool

    DaryHeap::output

    fn[T : Show] DaryHeap::output(self : DaryHeap[T], logger : &Logger) -> Unit

    DaryHeap::peek

    fn[T] DaryHeap::peek(self : DaryHeap[T]) -> T?

    The element a pop would return, without removing it, in O(1).

    DaryHeap::pop

    fn[T] DaryHeap::pop(self : DaryHeap[T]) -> T?

    Removes and returns the first element in O(log_d n), or None when the heap is empty.

    DaryHeap::push

    fn[T] DaryHeap::push(self : DaryHeap[T], value : T) -> Unit

    Adds one element in O(log_d n).

    test {
    let heap : @heap.DaryHeap[Int32] = try! @heap.DaryHeap::new()
    heap.push(2)
    heap.push(1)
    assert_true(heap.peek() == Some(1))
    }

    DaryHeap::push_pop

    fn[T] DaryHeap::push_pop(self : DaryHeap[T], value : T) -> T?

    Pushes value and pops the first element in one sift, which is Python's heappushpop: the result is value itself when it would be popped straight away, so a bound on a stream costs no tree update.

    On an empty heap this is a push that returns None.

    DaryHeap::replace

    fn[T] DaryHeap::replace(self : DaryHeap[T], value : T) -> T?

    Removes the first element and puts value in its place in one sift down, which is cheaper than pop followed by push. Returns the element removed.

    On an empty heap this is a plain push that returns None.

    DaryHeap::to_array

    fn[T] DaryHeap::to_array(self : DaryHeap[T]) -> Array[T]

    The elements in the heap's internal array order. Use into_sorted_array for the order the heap pops in.

    DaryHeap::to_string

    fn[T : Show] DaryHeap::to_string(self : DaryHeap[T]) -> String

    FibonacciHeap

    pub struct FibonacciHeap[T] {
    cmp : (T, T) -> Int
    values : Array[T?]
    parents : Array[Int]
    child : Array[Int]
    left : Array[Int]
    right : Array[Int]
    degree : Array[Int]
    marked : Array[Bool]
    generations : Array[UInt]
    free : Array[Int]
    min : Int
    len : Int
    }

    A Fibonacci heap: roots and children sit in circular doubly linked lists, so an insert only splices one node in, a meld only joins two lists, and a decrease_key only cuts one subtree loose — each of them constant amortised time. The price is paid on pop, which consolidates the roots by degree.

    test {
    let heap : @heap.FibonacciHeap[Int32] = @heap.FibonacciHeap::new()
    let a = heap.insert(5)
    let _ = heap.insert(2)
    let _ = heap.insert(8)
    assert_true(heap.peek() == Some(2))
    assert_true(heap.decrease_key(a, 1))
    assert_true(heap.pop() == Some(1))
    }

    FibonacciHeap::clear

    fn[T] FibonacciHeap::clear(self : FibonacciHeap[T]) -> Unit

    FibonacciHeap::contains

    fn[T] FibonacciHeap::contains(self : FibonacciHeap[T], key : HeapKey[T]) -> Bool

    FibonacciHeap::decrease_key

    fn[T] FibonacciHeap::decrease_key(self : FibonacciHeap[T], key : HeapKey[T], value : T) -> Bool

    Lowers the key of an entry that is already in the heap: a node that drops below its parent is cut loose, which costs nothing to undo later because the pop consolidates anyway. Refuses a value that is not a decrease.

    FibonacciHeap::get

    fn[T] FibonacciHeap::get(self : FibonacciHeap[T], key : HeapKey[T]) -> T?

    FibonacciHeap::insert

    fn[T] FibonacciHeap::insert(self : FibonacciHeap[T], value : T) -> HeapKey[T]

    FibonacciHeap::into_sorted_array

    fn[T] FibonacciHeap::into_sorted_array(self : FibonacciHeap[T]) -> Array[T]

    FibonacciHeap::is_empty

    fn[T] FibonacciHeap::is_empty(self : FibonacciHeap[T]) -> Bool

    FibonacciHeap::length

    fn[T] FibonacciHeap::length(self : FibonacciHeap[T]) -> Int

    FibonacciHeap::merge

    fn[T] FibonacciHeap::merge(self : FibonacciHeap[T], other : FibonacciHeap[T]) -> Unit

    FibonacciHeap::new

    fn[T : Compare + Eq] FibonacciHeap::new(order? : Order) -> FibonacciHeap[T]

    FibonacciHeap::new_by

    fn[T] FibonacciHeap::new_by(cmp~ : (T, T) -> Int) -> FibonacciHeap[T]

    FibonacciHeap::peek

    fn[T] FibonacciHeap::peek(self : FibonacciHeap[T]) -> T?

    FibonacciHeap::pop

    fn[T] FibonacciHeap::pop(self : FibonacciHeap[T]) -> T?

    FibonacciHeap::remove_at

    fn[T] FibonacciHeap::remove_at(self : FibonacciHeap[T], key : HeapKey[T]) -> T?

    FibonacciHeap::to_array

    fn[T] FibonacciHeap::to_array(self : FibonacciHeap[T]) -> Array[T]

    FibonacciHeap::update

    fn[T] FibonacciHeap::update(self : FibonacciHeap[T], key : HeapKey[T], value : T) -> Bool

    Replaces the value whatever its direction: a node whose value no longer fits under its parent is cut loose and the ancestors are repaired as a decrease_key would repair them.

    HeapKey

    pub(all) struct HeapKey[T] {
    index : Int
    generation : UInt
    }

    A stable handle to one entry of an addressable heap.

    index names the entry's slot and generation the state that slot was in when the handle was issued. A slot is reused after its entry is removed and the generation is then bumped, so a handle kept past a removal names nothing and every method taking one reports a miss instead of reaching the element that took the slot. The type parameter names the element type the handle came from, which keeps a handle from one heap type from being passed to another; it holds no data.
    impl Eq for HeapKey[T]
    impl Hash for HeapKey[T]
    impl Show for HeapKey[T]
    impl ToJson for HeapKey[T]

    HeapKey::equal

    fn[T] HeapKey::equal(self : HeapKey[T], other : HeapKey[T]) -> Bool

    HeapKey::hash

    fn[T] HeapKey::hash(self : HeapKey[T]) -> Int

    HeapKey::hash_combine

    fn[T] HeapKey::hash_combine(self : HeapKey[T], hasher : Hasher) -> Unit

    HeapKey::not_equal

    fn[T] HeapKey::not_equal(x : HeapKey[T], y : HeapKey[T]) -> Bool

    HeapKey::output

    fn[T] HeapKey::output(self : HeapKey[T], logger : &Logger) -> Unit

    HeapKey::to_json

    fn[T] HeapKey::to_json(self : HeapKey[T]) ->
    Json

    HeapKey::to_string

    fn[T] HeapKey::to_string(self : HeapKey[T]) -> String

    IndexHeap

    pub struct IndexHeap[T] {
    cmp : (T, T) -> Int
    values : Array[T?]
    generations : Array[UInt]
    positions : Array[Int]
    heap : Array[Int]
    free : Array[Int]
    len : Int
    }

    A binary heap whose entries are addressed by HeapKey: an update or a remove_at reaches one element without searching, because every slot knows its position in the heap array and every position knows its slot.

    test {
    let heap : @heap.IndexHeap[Int32] = @heap.IndexHeap::new()
    let a = heap.insert(5)
    let b = heap.insert(1)
    assert_true(heap.update(a, 0))
    assert_true(heap.peek() == Some(0))
    assert_true(heap.remove_at(b) == Some(1))
    assert_true(heap.length() == 1)
    }

    IndexHeap::clear

    fn[T] IndexHeap::clear(self : IndexHeap[T]) -> Unit

    IndexHeap::contains

    fn[T] IndexHeap::contains(self : IndexHeap[T], key : HeapKey[T]) -> Bool

    IndexHeap::copy

    fn[T] IndexHeap::copy(self : IndexHeap[T]) -> IndexHeap[T]

    IndexHeap::get

    fn[T] IndexHeap::get(self : IndexHeap[T], key : HeapKey[T]) -> T?

    IndexHeap::insert

    fn[T] IndexHeap::insert(self : IndexHeap[T], value : T) -> HeapKey[T]

    Stores value and returns the handle that addresses it.

    IndexHeap::into_sorted_array

    fn[T] IndexHeap::into_sorted_array(self : IndexHeap[T]) -> Array[T]

    The elements in pop order, emptying the heap.

    IndexHeap::is_empty

    fn[T] IndexHeap::is_empty(self : IndexHeap[T]) -> Bool

    IndexHeap::length

    fn[T] IndexHeap::length(self : IndexHeap[T]) -> Int

    IndexHeap::new

    fn[T : Compare + Eq] IndexHeap::new(order? : Order) -> IndexHeap[T]

    IndexHeap::new_by

    fn[T] IndexHeap::new_by(cmp~ : (T, T) -> Int) -> IndexHeap[T]

    IndexHeap::peek

    fn[T] IndexHeap::peek(self : IndexHeap[T]) -> T?

    IndexHeap::pop

    fn[T] IndexHeap::pop(self : IndexHeap[T]) -> T?

    IndexHeap::remove_at

    fn[T] IndexHeap::remove_at(self : IndexHeap[T], key : HeapKey[T]) -> T?

    IndexHeap::to_array

    fn[T] IndexHeap::to_array(self : IndexHeap[T]) -> Array[T]

    IndexHeap::update

    fn[T] IndexHeap::update(self : IndexHeap[T], key : HeapKey[T], value : T) -> Bool

    Replaces the element and restores the order around it, which is what makes this heap addressable: the entry may move up or down.

    MinMaxHeap

    pub struct MinMaxHeap[T] {
    cmp : (T, T) -> Int
    items : Array[T]
    }

    A double-ended priority queue: both the smallest and the largest element are one comparison away, and both can be popped in logarithmic time. The array alternates min levels and max levels, so the smallest is at the root and the largest is one of its two children.

    test {
    let heap : @heap.MinMaxHeap[Int32] = @heap.MinMaxHeap::new()
    for value in [5, 1, 9, 3, 7] {
    heap.push(value)
    }
    assert_true(heap.peek_min() == Some(1))
    assert_true(heap.peek_max() == Some(9))
    assert_true(heap.pop_min() == Some(1))
    assert_true(heap.pop_max() == Some(9))
    }

    MinMaxHeap::clear

    fn[T] MinMaxHeap::clear(self : MinMaxHeap[T]) -> Unit

    MinMaxHeap::copy

    fn[T] MinMaxHeap::copy(self : MinMaxHeap[T]) -> MinMaxHeap[T]

    MinMaxHeap::is_empty

    fn[T] MinMaxHeap::is_empty(self : MinMaxHeap[T]) -> Bool

    MinMaxHeap::length

    fn[T] MinMaxHeap::length(self : MinMaxHeap[T]) -> Int

    MinMaxHeap::new

    fn[T : Compare + Eq] MinMaxHeap::new() -> MinMaxHeap[T]

    MinMaxHeap::new_by

    fn[T] MinMaxHeap::new_by(cmp~ : (T, T) -> Int) -> MinMaxHeap[T]

    MinMaxHeap::peek_max

    fn[T] MinMaxHeap::peek_max(self : MinMaxHeap[T]) -> T?

    MinMaxHeap::peek_min

    fn[T] MinMaxHeap::peek_min(self : MinMaxHeap[T]) -> T?

    MinMaxHeap::pop_max

    fn[T] MinMaxHeap::pop_max(self : MinMaxHeap[T]) -> T?

    MinMaxHeap::pop_min

    fn[T] MinMaxHeap::pop_min(self : MinMaxHeap[T]) -> T?

    MinMaxHeap::push

    fn[T] MinMaxHeap::push(self : MinMaxHeap[T], value : T) -> Unit

    MinMaxHeap::to_array

    fn[T] MinMaxHeap::to_array(self : MinMaxHeap[T]) -> Array[T]

    Order

    pub(all) enum Order {
    Min
    Max
    } derive(Eq,
    Debug
    )

    Which end of the order a heap pops from.

    Min pops the element that compares smallest and is what Python's heapq and Java's PriorityQueue do; Max pops the largest and is what C++ and core's PriorityQueue do. The two are one comparator apart, so the direction is a value rather than a second type.
    impl Show for Order

    Order::equal

    fn Order::equal(Order, Order) -> Bool

    Order::not_equal

    fn Order::not_equal(x : Order, y : Order) -> Bool

    Order::output

    fn Order::output(self : Order, logger : &Logger) -> Unit

    Order::to_repr

    Order::to_string

    fn Order::to_string(self : Order) -> String

    PairingHeap

    pub struct PairingHeap[T] {
    cmp : (T, T) -> Int
    values : Array[T?]
    children : Array[Int]
    siblings : Array[Int]
    parents : Array[Int]
    generations : Array[UInt]
    free : Array[Int]
    root : Int
    len : Int
    }

    A heap of linked nodes: every node keeps its children in a list and a meld only links two roots, so insert and meld are constant time and a pop pays for the pairwise merging of the children it uncovers. Its update and remove_at reach a node through a HeapKey and detach it without a search, which is what a scheduler that cancels timers needs.

    test {
    let heap : @heap.PairingHeap[Int32] = @heap.PairingHeap::new()
    let a = heap.insert(5)
    let b = heap.insert(2)
    let _ = heap.insert(9)
    assert_true(heap.peek() == Some(2))
    assert_true(heap.update(a, 1))
    assert_true(heap.peek() == Some(1))
    assert_true(heap.remove_at(b) == Some(2))
    assert_true(heap.pop() == Some(1))
    }

    PairingHeap::clear

    fn[T] PairingHeap::clear(self : PairingHeap[T]) -> Unit

    PairingHeap::contains

    fn[T] PairingHeap::contains(self : PairingHeap[T], key : HeapKey[T]) -> Bool

    PairingHeap::get

    fn[T] PairingHeap::get(self : PairingHeap[T], key : HeapKey[T]) -> T?

    PairingHeap::insert

    fn[T] PairingHeap::insert(self : PairingHeap[T], value : T) -> HeapKey[T]

    PairingHeap::into_sorted_array

    fn[T] PairingHeap::into_sorted_array(self : PairingHeap[T]) -> Array[T]

    PairingHeap::is_empty

    fn[T] PairingHeap::is_empty(self : PairingHeap[T]) -> Bool

    PairingHeap::length

    fn[T] PairingHeap::length(self : PairingHeap[T]) -> Int

    PairingHeap::merge

    fn[T] PairingHeap::merge(self : PairingHeap[T], other : PairingHeap[T]) -> Unit

    PairingHeap::new

    fn[T : Compare + Eq] PairingHeap::new(order? : Order) -> PairingHeap[T]

    PairingHeap::new_by

    fn[T] PairingHeap::new_by(cmp~ : (T, T) -> Int) -> PairingHeap[T]

    PairingHeap::peek

    fn[T] PairingHeap::peek(self : PairingHeap[T]) -> T?

    PairingHeap::pop

    fn[T] PairingHeap::pop(self : PairingHeap[T]) -> T?

    PairingHeap::remove_at

    fn[T] PairingHeap::remove_at(self : PairingHeap[T], key : HeapKey[T]) -> T?

    PairingHeap::to_array

    fn[T] PairingHeap::to_array(self : PairingHeap[T]) -> Array[T]

    PairingHeap::update

    fn[T] PairingHeap::update(self : PairingHeap[T], key : HeapKey[T], value : T) -> Bool

    RadixHeap

    pub struct RadixHeap[T] {
    buckets : Array[Array[(UInt64, T)]]
    last : UInt64
    len : Int
    }

    A monotone heap over UInt64 keys: the key of a pushed entry may not be smaller than the key of the last one popped. Under that rule a pop costs O(log C) where C is the width of the key space, and it never compares two keys of different buckets — the bucket a key falls in already says which is smaller. That is what makes it a step faster than a comparison heap on integer keys, and why a key below the last pop is refused rather than reordered.

    test {
    let heap : @heap.RadixHeap[String] = @heap.RadixHeap::new()
    heap.push(5UL, "five")
    heap.push(1UL, "one")
    heap.push(9UL, "nine")
    assert_true(heap.pop_min() == Some((1UL, "one")))
    assert_true(heap.pop_min() == Some((5UL, "five")))
    }

    RadixHeap::clear

    fn[T] RadixHeap::clear(self : RadixHeap[T]) -> Unit

    RadixHeap::is_empty

    fn[T] RadixHeap::is_empty(self : RadixHeap[T]) -> Bool

    RadixHeap::length

    fn[T] RadixHeap::length(self : RadixHeap[T]) -> Int

    RadixHeap::new

    fn[T] RadixHeap::new() -> RadixHeap[T]

    RadixHeap::peek_key

    fn[T] RadixHeap::peek_key(self : RadixHeap[T]) -> UInt64?

    RadixHeap::pop_min

    fn[T] RadixHeap::pop_min(self : RadixHeap[T]) -> (UInt64, T)?

    RadixHeap::push

    fn[T] RadixHeap::push(self : RadixHeap[T], key : UInt64, value : T) -> Unit raise
    Refused

    Adds an entry whose key is not below the last key popped.