moonbitstack/moonstl/tree does not have a README file

    ArenaTree

    pub struct ArenaTree[T] {
    values : Array[T?]
    generations : Array[UInt]
    free : Array[Int]
    parents : Array[Int]
    first_child : Array[Int]
    last_child : Array[Int]
    previous : Array[Int]
    next : Array[Int]
    root : Int
    len : Int
    }

    A tree whose nodes live in one arena and are reached by id: a node knows its parent, its first and last child, and its two siblings, so every step of a walk is a field read and no pointer chases the allocator. Children are kept in insertion order, and sort_children reorders them by their own values.

    test {
    let tree : @tree.ArenaTree[String] = @tree.ArenaTree::new()
    let root = tree.add("root")
    let a = tree.add_child(root, "a")
    let _ = tree.add_child(root, "b")
    let _ = tree.add_child(a, "a1")
    assert_true(tree.length() == 4)
    assert_true(tree.children(root).length() == 2)
    assert_true(tree.descendants(root).to_array().length() == 3)
    assert_true(tree.remove(a) == Some("a"))
    assert_true(tree.length() == 2)
    }

    ArenaTree::add

    fn[T] ArenaTree::add(self : ArenaTree[T], value : T) -> TreeId

    Adds a detached node, which becomes a root of its own.

    ArenaTree::add_child

    fn[T] ArenaTree::add_child(self : ArenaTree[T], parent : TreeId, value : T) -> TreeId

    ArenaTree::ancestors

    fn[T] ArenaTree::ancestors(self : ArenaTree[T], id : TreeId) -> Iter[TreeId]

    The root first, then each ancestor up to it.

    ArenaTree::children

    fn[T] ArenaTree::children(self : ArenaTree[T], id : TreeId) -> Array[TreeId]

    The ids of the children, in order.

    ArenaTree::clear

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

    ArenaTree::contains

    fn[T] ArenaTree::contains(self : ArenaTree[T], id : TreeId) -> Bool

    ArenaTree::copy

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

    ArenaTree::descendants

    fn[T] ArenaTree::descendants(self : ArenaTree[T], id : TreeId) -> Iter[TreeId]

    The children of a node, and their children, depth first and left to right.

    ArenaTree::detach

    fn[T] ArenaTree::detach(self : ArenaTree[T], id : TreeId) -> ArenaTree[T]?

    Cuts a subtree loose and returns it as a tree of its own. The copy owns its nodes, so the ids of the returned tree are its own; the original keeps its ids. The cost is the size of the subtree, because the nodes are rebuilt.

    ArenaTree::first_child

    fn[T] ArenaTree::first_child(self : ArenaTree[T], id : TreeId) -> TreeId?

    ArenaTree::get

    fn[T] ArenaTree::get(self : ArenaTree[T], id : TreeId) -> T?

    ArenaTree::insert_after

    fn[T] ArenaTree::insert_after(self : ArenaTree[T], sibling : TreeId, value : T) -> TreeId

    ArenaTree::insert_before

    fn[T] ArenaTree::insert_before(self : ArenaTree[T], sibling : TreeId, value : T) -> TreeId

    ArenaTree::is_empty

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

    ArenaTree::length

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

    The number of nodes.

    ArenaTree::new

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

    ArenaTree::next_sibling

    fn[T] ArenaTree::next_sibling(self : ArenaTree[T], id : TreeId) -> TreeId?

    ArenaTree::parent

    fn[T] ArenaTree::parent(self : ArenaTree[T], id : TreeId) -> TreeId?

    ArenaTree::postorder

    fn[T] ArenaTree::postorder(self : ArenaTree[T], id : TreeId) -> Iter[TreeId]

    The subtree in postorder: every child before its parent.

    ArenaTree::preorder

    fn[T] ArenaTree::preorder(self : ArenaTree[T], id : TreeId) -> Iter[TreeId]

    The whole tree in preorder, the node itself first.

    ArenaTree::prepend_child

    fn[T] ArenaTree::prepend_child(self : ArenaTree[T], parent : TreeId, value : T) -> TreeId

    ArenaTree::previous_sibling

    fn[T] ArenaTree::previous_sibling(self : ArenaTree[T], id : TreeId) -> TreeId?

    ArenaTree::remove

    fn[T] ArenaTree::remove(self : ArenaTree[T], id : TreeId) -> T?

    Removes the node and everything below it, returning the value that was on it.

    ArenaTree::set

    fn[T] ArenaTree::set(self : ArenaTree[T], id : TreeId, value : T) -> Bool

    ArenaTree::siblings

    fn[T] ArenaTree::siblings(self : ArenaTree[T], id : TreeId) -> Array[TreeId]

    The siblings of a node, the node itself included, in order.

    ArenaTree::sort_children

    fn[T] ArenaTree::sort_children(self : ArenaTree[T], id : TreeId, cmp : (T, T) -> Int) -> Unit

    Reorders the children of id by their own values, keeping the links intact.

    DisjointSet

    pub struct DisjointSet {
    parents : Array[Int]
    sizes : Array[Int]
    sets : Int
    }

    Union-find over 0 ..< n: every set is a tree whose root carries its size, and find halves the path on the way up so repeated queries flatten the structure without a second pass. Union by size keeps the trees shallow, which together with path halving makes the amortised cost of an operation inverse Ackermann — effectively constant.

    test {
    let sets : @tree.DisjointSet = @tree.DisjointSet::new()
    let a = sets.add()
    let b = sets.add()
    let c = sets.add()
    assert_true(sets.union(a, b))
    assert_true(sets.connected(a, b))
    assert_true(!sets.connected(a, c))
    assert_true(sets.set_count() == 2)
    }

    DisjointSet::add

    fn DisjointSet::add(self : DisjointSet) -> Int

    Adds a singleton set and returns its index.

    DisjointSet::component_size

    fn DisjointSet::component_size(self : DisjointSet, element : Int) -> Int

    The size of the set that holds element.

    DisjointSet::connected

    fn DisjointSet::connected(self : DisjointSet, a : Int, b : Int) -> Bool

    DisjointSet::find

    fn DisjointSet::find(self : DisjointSet, element : Int) -> Int

    The representative of the set that holds element, with the path halved on the way.

    DisjointSet::length

    fn DisjointSet::length(self : DisjointSet) -> Int

    The number of elements, not of sets.

    DisjointSet::new

    DisjointSet::set_count

    fn DisjointSet::set_count(self : DisjointSet) -> Int

    DisjointSet::set_size

    fn DisjointSet::set_size(self : DisjointSet, root : Int) -> Int

    The size of the set whose representative is root, which is what a caller that already holds a root avoids a second find with.

    DisjointSet::to_sets

    fn DisjointSet::to_sets(self : DisjointSet) -> Array[Array[Int]]

    Every set as the array of its members, representatives first.

    DisjointSet::union

    fn DisjointSet::union(self : DisjointSet, a : Int, b : Int) -> Bool

    Joins the sets of two elements and reports whether they were apart.

    DisjointSetMap

    pub struct DisjointSetMap[K] {
    indices : Map[K, Int]
    sets : DisjointSet
    keys : Array[K]
    }

    Union-find over keys of any type: the key is interned to an index on first use, and the union-find runs on the indices.

    test {
    let sets : @tree.DisjointSetMap[String] = @tree.DisjointSetMap::new()
    assert_true(sets.union("a", "b"))
    assert_true(sets.connected("a", "b"))
    assert_true(!sets.connected("a", "c"))
    }

    DisjointSetMap::component_size

    fn[K : Hash + Eq] DisjointSetMap::component_size(self : DisjointSetMap[K], key : K) -> Int

    The size of the set that holds key, zero when the key was never seen.

    DisjointSetMap::connected

    fn[K : Hash + Eq] DisjointSetMap::connected(self : DisjointSetMap[K], a : K, b : K) -> Bool

    DisjointSetMap::find

    fn[K : Hash + Eq] DisjointSetMap::find(self : DisjointSetMap[K], key : K) -> K?

    DisjointSetMap::intern

    fn[K : Hash + Eq] DisjointSetMap::intern(self : DisjointSetMap[K], key : K) -> Int

    The index of a key, adding it as a singleton the first time it is seen.

    DisjointSetMap::length

    fn[K] DisjointSetMap::length(self : DisjointSetMap[K]) -> Int

    DisjointSetMap::new

    fn[K : Hash + Eq] DisjointSetMap::new() -> DisjointSetMap[K]

    DisjointSetMap::set_count

    fn[K] DisjointSetMap::set_count(self : DisjointSetMap[K]) -> Int

    DisjointSetMap::to_sets

    fn[K] DisjointSetMap::to_sets(self : DisjointSetMap[K]) -> Array[Array[K]]

    Every set as the array of its members.

    DisjointSetMap::union

    fn[K : Hash + Eq] DisjointSetMap::union(self : DisjointSetMap[K], a : K, b : K) -> Bool

    Fenwick

    pub struct Fenwick[T] {
    tree : Array[T]
    values : Array[T]
    length_ : Int
    }

    A Fenwick tree: tree[i] holds the sum of the i & -i elements that end at i, so a prefix sum reads one path to zero and an update writes one path to the end. Both are O(log n) with small constants, which is why it beats a segment tree for sums that only ever grow at a point.

    test {
    let fenwick : @tree.Fenwick[Int32] = @tree.Fenwick::new(length=5)
    fenwick.add(0, 3)
    fenwick.add(2, 4)
    assert_true(fenwick.prefix_sum(3) == 7)
    assert_true(fenwick.range_sum(1, 3) == 4)
    let _ = fenwick.set(0, 10)
    assert_true(fenwick.get(0) == Some(10))
    assert_true(fenwick.lower_bound(5) == Some(0))
    }

    Fenwick::add

    fn[T : Add] Fenwick::add(self : Fenwick[T], index : Int, delta : T) -> Unit

    Fenwick::from_array

    fn[T : Add + Sub + Default] Fenwick::from_array(values : ArrayView[T]) -> Fenwick[T]

    Fenwick::get

    fn[T] Fenwick::get(self : Fenwick[T], index : Int) -> T?

    Fenwick::length

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

    Fenwick::lower_bound

    fn[T : Sub + Compare + Eq] Fenwick::lower_bound(self : Fenwick[T], target : T) -> Int?

    The first index whose prefix sum is strictly greater than target, which is how a Fenwick tree answers "where does this weight get spent" while every value stays non-negative. None when the whole tree does not reach it.

    Fenwick::new

    fn[T : Default] Fenwick::new(length~ : Int) -> Fenwick[T]

    Fenwick::prefix_sum

    fn[T : Add + Default] Fenwick::prefix_sum(self : Fenwick[T], end : Int) -> T

    The sum of the first end elements.

    Fenwick::range_sum

    fn[T : Add + Sub + Default] Fenwick::range_sum(self : Fenwick[T], start : Int, end : Int) -> T

    The sum of [start, end).

    Fenwick::set

    fn[T : Add + Sub] Fenwick::set(self : Fenwick[T], index : Int, value : T) -> Bool

    IntervalKey

    pub(all) struct IntervalKey[K] {
    index : Int
    generation : UInt
    } derive(Eq, Hash,
    Debug
    )

    A handle to one interval of an IntervalTree. Like a slot key, it carries the generation of the slot it was handed out for, so a handle to a removed interval reads as absent instead of reaching a later one.

    IntervalKey::equal

    fn[K : Eq] IntervalKey::equal(IntervalKey[K], IntervalKey[K]) -> Bool

    IntervalKey::hash

    fn[K : Hash] IntervalKey::hash(self : IntervalKey[K]) -> Int

    IntervalKey::hash_combine

    fn[K : Hash] IntervalKey::hash_combine(IntervalKey[K], Hasher) -> Unit

    IntervalKey::not_equal

    fn[K : Eq] IntervalKey::not_equal(x : IntervalKey[K], y : IntervalKey[K]) -> Bool

    IntervalTree

    pub struct IntervalTree[K, V] {
    cmp : (K, K) -> Int
    starts : Array[K?]
    ends : Array[K?]
    values : Array[V?]
    generations : Array[UInt]
    free : Array[Int]
    order : Array[Int]
    max_ends : Array[K?]
    len : Int
    }

    Intervals over a key type, kept sorted by start with a running maximum of the ends. That prefix maximum is what a point query walks back through: once a prefix can no longer reach the point, no interval before it can either, so the scan stops. Intervals are half-open, [start, end).

    test {
    let tree : @tree.IntervalTree[Int32, String] = @tree.IntervalTree::new()
    let _ = tree.insert(start=0, end=10, "a")
    let _ = tree.insert(start=5, end=15, "b")
    assert_true(tree.query_point(7).length() == 2)
    assert_true(tree.query_point(12).length() == 1)
    assert_true(tree.query_point(20).length() == 0)
    }

    IntervalTree::clear

    fn[K, V] IntervalTree::clear(self : IntervalTree[K, V]) -> Unit

    IntervalTree::copy

    fn[K, V] IntervalTree::copy(self : IntervalTree[K, V]) -> IntervalTree[K, V]

    IntervalTree::get

    fn[K, V] IntervalTree::get(self : IntervalTree[K, V], key : IntervalKey[K]) -> (K, K, V)?

    IntervalTree::insert

    fn[K, V] IntervalTree::insert(self : IntervalTree[K, V], start~ : K, end~ : K, value : V) -> IntervalKey[K]

    IntervalTree::is_empty

    fn[K, V] IntervalTree::is_empty(self : IntervalTree[K, V]) -> Bool

    IntervalTree::iter

    fn[K, V] IntervalTree::iter(self : IntervalTree[K, V]) -> Iter[(K, K, V)]

    The intervals in start order.

    IntervalTree::length

    fn[K, V] IntervalTree::length(self : IntervalTree[K, V]) -> Int

    IntervalTree::new

    fn[K : Compare + Eq, V] IntervalTree::new() -> IntervalTree[K, V]

    IntervalTree::new_by

    fn[K, V] IntervalTree::new_by(cmp~ : (K, K) -> Int) -> IntervalTree[K, V]

    IntervalTree::query_overlap

    fn[K, V] IntervalTree::query_overlap(self : IntervalTree[K, V], start~ : K, end~ : K) -> Array[(K, K, V)]

    Every interval that meets [start, end).

    IntervalTree::query_point

    fn[K, V] IntervalTree::query_point(self : IntervalTree[K, V], point : K) -> Array[(K, K, V)]

    Every interval that covers point.

    IntervalTree::remove

    fn[K, V] IntervalTree::remove(self : IntervalTree[K, V], key : IntervalKey[K]) -> (K, K, V)?

    LazySegmentTree

    pub struct LazySegmentTree[T, F] {
    op : (T, T) -> T
    identity : T
    apply : (F, T, Int) -> T
    compose : (F, F) -> F
    none : F
    size : Int
    nodes : Array[T]
    tags : Array[F]
    }

    A segment tree that also accepts a range update: a tag is applied to a whole cover of a range and pushed down only when a later query or a partial update has to look inside. apply says what a tag does to an aggregate, compose merges an older tag into a newer one, and none is the tag that does nothing.

    test {
    let tree : @tree.LazySegmentTree[Int32, Int32] = @tree.LazySegmentTree::from_array(
    [1, 1, 1, 1],
    op=(a, b) => a + b,
    identity=0,
    apply=(tag, value, span) => value + tag * span,
    compose=(older, newer) => older + newer,
    none=0,
    )
    tree.range_update(1, 3, 5)
    assert_true(tree.query(0, 4) == 14)
    assert_true(tree.query(1, 2) == 6)
    }

    LazySegmentTree::from_array

    fn[T, F] LazySegmentTree::from_array(values : ArrayView[T], op~ : (T, T) -> T, identity~ : T, apply~ : (F, T, Int) -> T, compose~ : (F, F) -> F, none~ : F) -> LazySegmentTree[T, F]

    LazySegmentTree::get

    fn[T, F] LazySegmentTree::get(self : LazySegmentTree[T, F], index : Int) -> T?

    LazySegmentTree::new

    fn[T, F] LazySegmentTree::new(length~ : Int, op~ : (T, T) -> T, identity~ : T, apply~ : (F, T, Int) -> T, compose~ : (F, F) -> F, none~ : F) -> LazySegmentTree[T, F]

    LazySegmentTree::query

    fn[T, F] LazySegmentTree::query(self : LazySegmentTree[T, F], start : Int, end : Int) -> T

    LazySegmentTree::range_update

    fn[T, F] LazySegmentTree::range_update(self : LazySegmentTree[T, F], start : Int, end : Int, tag : F) -> Unit

    LazySegmentTree::set

    fn[T, F] LazySegmentTree::set(self : LazySegmentTree[T, F], index : Int, value : T) -> Bool

    OrderStatisticTree

    pub struct OrderStatisticTree[T] {
    cmp : (T, T) -> Int
    keys : Array[T?]
    left : Array[Int]
    right : Array[Int]
    sizes : Array[Int]
    priorities : Array[UInt64]
    root : Int
    len : Int
    seed : UInt64
    }

    A search tree that also answers by position: every node carries the size of its subtree, so select and rank walk one path instead of counting. Duplicates are not stored. The shape is that of a treap, which is what keeps the depth logarithmic without rebalancing after every insert.

    test {
    let tree : @tree.OrderStatisticTree[Int32] = @tree.OrderStatisticTree::new()
    for value in [5, 1, 9, 3] {
    let _ = tree.insert(value)
    }
    assert_true(tree.select(0) == Some(1))
    assert_true(tree.select(3) == Some(9))
    assert_true(tree.rank(5) == 2)
    assert_true(tree.count_range(2, 9) == 2)
    }

    OrderStatisticTree::clear

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

    OrderStatisticTree::contains

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

    OrderStatisticTree::copy

    OrderStatisticTree::count_less

    fn[T] OrderStatisticTree::count_less(self : OrderStatisticTree[T], key : T) -> Int

    OrderStatisticTree::count_range

    fn[T] OrderStatisticTree::count_range(self : OrderStatisticTree[T], start : T, end : T) -> Int

    The number of elements in [start, end), both ends compared by the tree's own comparator.

    OrderStatisticTree::first

    fn[T] OrderStatisticTree::first(self : OrderStatisticTree[T]) -> T?

    OrderStatisticTree::insert

    fn[T] OrderStatisticTree::insert(self : OrderStatisticTree[T], key : T) -> Bool

    OrderStatisticTree::is_empty

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

    OrderStatisticTree::iter

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

    OrderStatisticTree::last

    fn[T] OrderStatisticTree::last(self : OrderStatisticTree[T]) -> T?

    OrderStatisticTree::length

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

    OrderStatisticTree::new

    OrderStatisticTree::new_by

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

    OrderStatisticTree::range

    fn[T] OrderStatisticTree::range(self : OrderStatisticTree[T], start : T, end : T) -> Iter[T]

    OrderStatisticTree::rank

    fn[T] OrderStatisticTree::rank(self : OrderStatisticTree[T], key : T) -> Int

    The number of elements smaller than key.

    OrderStatisticTree::remove

    fn[T] OrderStatisticTree::remove(self : OrderStatisticTree[T], key : T) -> Bool

    OrderStatisticTree::select

    fn[T] OrderStatisticTree::select(self : OrderStatisticTree[T], index : Int) -> T?

    The element at position index, counting from zero.

    OrderStatisticTree::to_array

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

    SegmentTree

    pub struct SegmentTree[T] {
    op : (T, T) -> T
    identity : T
    size : Int
    nodes : Array[T]
    }

    A range aggregate over a fixed array: the leaves are the elements, an inner node is op of its two children, and a query combines the O(log n) nodes that cover a half-open range. The operation has to be associative, and identity has to leave the other operand alone, which is what lets a query start from nothing.

    test {
    let tree : @tree.SegmentTree[Int32] = @tree.SegmentTree::from_array(
    [3, 1, 4, 1, 5],
    op=(a, b) => a + b,
    identity=0,
    )
    assert_true(tree.query(0, 3) == 8)
    assert_true(tree.query_all() == 14)
    let _ = tree.set(1, 10)
    assert_true(tree.query(0, 3) == 17)
    assert_true(tree.first_where(x => x >= 17) == Some(2))
    }

    SegmentTree::copy

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

    SegmentTree::first_where

    fn[T] SegmentTree::first_where(self : SegmentTree[T], predicate : (T) -> Bool) -> Int?

    The first position whose prefix aggregate satisfies predicate, or None. The descent relies on the predicate holding for a prefix once it holds for a smaller one, which is what makes a segment tree able to answer "where does this threshold get crossed" in O(log n).

    SegmentTree::from_array

    fn[T] SegmentTree::from_array(values : ArrayView[T], op~ : (T, T) -> T, identity~ : T) -> SegmentTree[T]

    SegmentTree::get

    fn[T] SegmentTree::get(self : SegmentTree[T], index : Int) -> T?

    SegmentTree::length

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

    SegmentTree::new

    fn[T] SegmentTree::new(length~ : Int, op~ : (T, T) -> T, identity~ : T) -> SegmentTree[T]

    A tree over length positions, every one of them identity.

    SegmentTree::query

    fn[T] SegmentTree::query(self : SegmentTree[T], start : Int, end : Int) -> T

    The aggregate over [start, end), identity when the range is empty.

    SegmentTree::query_all

    fn[T] SegmentTree::query_all(self : SegmentTree[T]) -> T

    SegmentTree::set

    fn[T] SegmentTree::set(self : SegmentTree[T], index : Int, value : T) -> Bool

    SegmentTree::to_array

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

    SkipList

    pub struct SkipList[T] {
    cmp : (T, T) -> Int
    options : SkipListOptions
    values : Array[T?]
    nexts : Array[Array[Int]]
    spans : Array[Array[Int]]
    len : Int
    rng : UInt64
    }

    A probabilistic ordered set. A node takes part in one level with probability p and in the next with p again, so a search skips most of the list at the top and refines as it descends; every level also stores how many nodes it spans, which is what makes rank and select a single descent. The shape is drawn from the seed, so a run replays exactly.

    test {
    let list : @tree.SkipList[Int32] = @tree.SkipList::new()
    for value in [5, 1, 9, 3] {
    let _ = list.insert(value)
    }
    assert_true(list.to_array() == [1, 3, 5, 9])
    assert_true(list.rank(5) == 2)
    assert_true(list.select(2) == Some(5))
    }

    SkipList::clear

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

    SkipList::contains

    fn[T] SkipList::contains(self : SkipList[T], value : T) -> Bool

    SkipList::first

    fn[T] SkipList::first(self : SkipList[T]) -> T?

    SkipList::insert

    fn[T] SkipList::insert(self : SkipList[T], value : T) -> Bool

    Adds value and reports whether it was new.

    SkipList::is_empty

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

    SkipList::iter

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

    SkipList::last

    fn[T] SkipList::last(self : SkipList[T]) -> T?

    SkipList::length

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

    SkipList::new

    fn[T : Compare + Eq] SkipList::new(skip_list_options? : SkipListOptions) -> SkipList[T]

    SkipList::new_by

    fn[T] SkipList::new_by(cmp~ : (T, T) -> Int, skip_list_options? : SkipListOptions) -> SkipList[T]

    SkipList::range

    fn[T] SkipList::range(self : SkipList[T], start : T, end : T) -> Iter[T]

    The elements between start and end, both included by the list's own comparator.

    SkipList::rank

    fn[T] SkipList::rank(self : SkipList[T], value : T) -> Int

    The number of elements smaller than value.

    SkipList::remove

    fn[T] SkipList::remove(self : SkipList[T], value : T) -> Bool

    SkipList::select

    fn[T] SkipList::select(self : SkipList[T], index : Int) -> T?

    The element at position index, counting from zero.

    SkipList::to_array

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

    SkipListOptions

    pub(all) struct SkipListOptions {
    probability : Double
    max_level : Int
    seed : Int
    } derive(Eq,
    Debug
    )

    The shape of a skip list: how often a node is promoted to the next level, the highest level it may reach, and the seed its coin flips come from. The probability of 0.25 is what Redis uses, which keeps the level count low while keeping the paths short.

    SkipListOptions::equal

    SkipListOptions::not_equal

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

    Treap

    pub struct Treap[K, V] {
    cmp : (K, K) -> Int
    keys : Array[K?]
    values : Array[V?]
    left : Array[Int]
    right : Array[Int]
    priorities : Array[UInt64]
    root : Int
    len : Int
    seed : UInt64
    }

    A map held as a treap: the keys are kept in order, each node carries a random priority that keeps the tree balanced, and split and merge cut and join in one path. range walks the keys in order between two bounds.

    test {
    let tree : @tree.Treap[Int32, String] = @tree.Treap::new()
    let _ = tree.set(2, "b")
    let _ = tree.set(1, "a")
    let _ = tree.set(3, "c")
    assert_true(tree.get(2) == Some("b"))
    assert_true(tree.to_array() == [(1, "a"), (2, "b"), (3, "c")])
    assert_true(tree.remove(2) == Some("b"))
    }

    Treap::clear

    fn[K, V] Treap::clear(self : Treap[K, V]) -> Unit

    Treap::contains

    fn[K, V] Treap::contains(self : Treap[K, V], key : K) -> Bool

    Treap::first

    fn[K, V] Treap::first(self : Treap[K, V]) -> (K, V)?

    Treap::get

    fn[K, V] Treap::get(self : Treap[K, V], key : K) -> V?

    Treap::is_empty

    fn[K, V] Treap::is_empty(self : Treap[K, V]) -> Bool

    Treap::iter

    fn[K, V] Treap::iter(self : Treap[K, V]) -> Iter[(K, V)]

    Treap::last

    fn[K, V] Treap::last(self : Treap[K, V]) -> (K, V)?

    Treap::length

    fn[K, V] Treap::length(self : Treap[K, V]) -> Int

    Treap::merge

    fn[K, V] Treap::merge(self : Treap[K, V], other : Treap[K, V]) -> Unit

    Joins two trees whose key ranges do not interleave.

    Treap::new

    fn[K : Compare + Eq, V] Treap::new() -> Treap[K, V]

    Treap::new_by

    fn[K, V] Treap::new_by(cmp~ : (K, K) -> Int) -> Treap[K, V]

    Treap::range

    fn[K, V] Treap::range(self : Treap[K, V], start : K, end : K) -> Iter[(K, V)]

    Treap::remove

    fn[K, V] Treap::remove(self : Treap[K, V], key : K) -> V?

    Treap::set

    fn[K, V] Treap::set(self : Treap[K, V], key : K, value : V) -> V?

    Treap::split

    fn[K, V] Treap::split(self : Treap[K, V], key : K) -> (Treap[K, V], Treap[K, V])

    Splits the tree at key into the part below it and the part at or above it.

    Treap::to_array

    fn[K, V] Treap::to_array(self : Treap[K, V]) -> Array[(K, V)]

    TreeId

    pub(all) struct TreeId {
    index : Int
    generation : UInt
    } derive(Eq, Hash,
    Debug
    )

    A handle to one node of an ArenaTree: the slot the node occupies and the generation of that slot when the handle was handed out, so a handle to a removed node reads as absent rather than reaching whoever took the slot.

    TreeId::equal

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

    TreeId::hash

    fn TreeId::hash(self : TreeId) -> Int

    TreeId::hash_combine

    fn TreeId::hash_combine(TreeId, Hasher) -> Unit

    TreeId::not_equal

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

    TreeId::to_repr

    skip_list_options

    let skip_list_options : SkipListOptions

    The preset: a quarter of the nodes climb to the next level, and thirty-two levels cover 4^32 entries.