For the complete documentation index, see llms.txt. This page is also available as Markdown.

(lispkit wt-tree)

Library (lispkit wt-tree) implements weight-balanced binary trees, a persistent, ordered key/value data structure. A wt-tree maps keys to values (like a hash table), but, unlike a hash table, keeps its entries ordered according to a user-supplied ordering predicate on the keys and provides efficient positional (rank-based) access, range splitting, and set-theoretic operations (union, intersection, difference, subset test) on the key sets of two trees. The implementation is an enhanced and bug-corrected variant of Stephen Adams' weight-balanced trees, following Yoichi Hirai and Kazuhiko Yamamoto, "Balancing weight-balanced trees", Journal of Functional Programming, 21(3):287-307, 2011.

WT-trees are persistent: operations such as wt-tree/add or wt-tree/delete return a new tree and leave the argument tree unchanged, sharing structure with it. For performance-sensitive code, destructive counterparts (wt-tree/add!, wt-tree/delete!, wt-tree/delete-min!) are also provided, mutating a tree in place.

Tree types

Every wt-tree is created with respect to a tree type, an object that bundles the strict ordering predicate (key<?) used to compare keys together with the tree-type-specific implementations of all wt-tree operations. Two trees can only be combined with each other (e.g. via wt-tree/union) if they were created with the very same tree type object.

(make-wt-tree-type key<?)

Returns a new tree type whose keys are ordered by the strict ordering predicate key<?, i.e. a procedure of two arguments returning #t if and only if its first argument is strictly less than its second.

(make-comparator-wt-tree-type comp)

Returns a new tree type whose keys are ordered according to the ordering predicate of comparator comp (see comparator-ordering-predicate of library (lispkit comparator)).

(wt-tree-type? obj)

Returns #t if obj is a tree type (as created by make-wt-tree-type, make-comparator-wt-tree-type, or one of the predefined tree types below), #f otherwise.

wt-tree-type-tag

Symbol representing the wt-tree-type type. The type-of procedure of library (lispkit type) returns a list starting with this symbol for tree type objects (not for wt-tree instances themselves; use wt-tree-type? respectively wt-tree? to distinguish the two).

number-wt-type

Predefined tree type ordering keys via <, i.e. for using real numbers as keys.

string-wt-type

Predefined tree type ordering keys via string<?, i.e. for using strings as keys.

string-ci-wt-type

Predefined tree type ordering keys via string-ci<?, i.e. for using strings as keys, ignoring case.

char-wt-type

Predefined tree type ordering keys via char<?, i.e. for using characters as keys.

char-ci-wt-type

Predefined tree type ordering keys via char-ci<?, i.e. for using characters as keys, ignoring case.

Constructing WT-Trees

(make-wt-tree) (make-wt-tree type)

Returns a new, empty wt-tree of tree type type. The default for type is number-wt-type.

(singleton-wt-tree key value) (singleton-wt-tree type key value)

Returns a new wt-tree of tree type type containing a single entry mapping key to value. The default for type is number-wt-type.

(alist->wt-tree type alist)

Returns a new wt-tree of tree type type, populated with the (key . value) associations of association list alist. If alist contains several entries for the same key, the entry that appears later in alist takes precedence.

(wt-tree? obj)

Returns #t if obj is a wt-tree, #f otherwise.

(wt-tree/copy tree)

Returns a new wt-tree with the same tree type, keys, and values as tree. Since wt-trees are persistent, wt-tree/copy is a cheap, O(1) operation; the copy initially shares its internal representation with tree, but the two trees evolve independently from each other, in particular with respect to the destructive operations wt-tree/add!, wt-tree/delete!, and wt-tree/delete-min!.

(wt-tree/valid? tree)

Returns #t if wt-tree tree satisfies the weight-balance and ordering invariants of the underlying tree implementation, #f otherwise. Since these invariants are maintained automatically by all wt-tree operations, this predicate is primarily useful for testing and debugging purposes.

Basic operations

(wt-tree/empty? tree)

Returns #t if wt-tree tree contains no entries, #f otherwise.

(wt-tree/size tree)

Returns the number of entries in wt-tree tree.

(wt-tree/add tree key value)

Returns a new wt-tree, like tree but with key mapped to value. If key is already present in tree, its associated value is replaced; tree itself remains unchanged.

(wt-tree/add! tree key value)

Destructively adds an entry mapping key to value to wt-tree tree, replacing any value that key was previously mapped to. Returns an unspecified result.

(wt-tree/delete tree key)

Returns a new wt-tree, like tree but with any entry for key removed. If key is not present in tree, a copy of tree is returned. tree itself remains unchanged.

(wt-tree/delete! tree key)

Destructively removes the entry for key, if any, from wt-tree tree. Returns an unspecified result.

(wt-tree/member? key tree)

Returns #t if wt-tree tree contains an entry for key, #f otherwise. Note that, unlike most other procedures of this library, wt-tree/member? expects key as its first and tree as its second argument.

(wt-tree/lookup tree key default)

Returns the value associated with key in wt-tree tree, or default if tree does not contain an entry for key.

Ordered and positional access

Since the entries of a wt-tree are kept in key order, they can also be accessed by their zero-based position (rank) in this order, from the smallest key (position 0) to the largest key (position (- (wt-tree/size tree) 1)).

(wt-tree/index tree index)

Returns the key at position index of wt-tree tree, in ascending key order. Signals an error if index is not in the range [0, (wt-tree/size tree)).

(wt-tree/index-datum tree index)

Like wt-tree/index, but returns the value associated with the key at position index instead of the key itself.

(wt-tree/index-pair tree index)

Like wt-tree/index, but returns a pair (key . value) for the entry at position index.

(wt-tree/rank tree key)

Returns the zero-based position of key within wt-tree tree in ascending key order, or #f if tree does not contain an entry for key. wt-tree/rank is the inverse operation of wt-tree/index.

(wt-tree/min tree)

Returns the smallest key of wt-tree tree. Signals an error if tree is empty.

(wt-tree/min-datum tree)

Returns the value associated with the smallest key of wt-tree tree. Signals an error if tree is empty.

(wt-tree/min-pair tree)

Returns a pair (key . value) for the entry with the smallest key of wt-tree tree. Signals an error if tree is empty.

(wt-tree/delete-min tree)

Returns a new wt-tree, like tree but with the entry for the smallest key removed. tree itself remains unchanged. Signals an error if tree is empty.

(wt-tree/delete-min! tree)

Destructively removes the entry for the smallest key from wt-tree tree. Returns an unspecified result. Signals an error if tree is empty.

Splitting trees

(wt-tree/split< tree key)

Returns a new wt-tree containing all entries of tree whose key is strictly less than key (the entry for key itself, if present, is excluded).

(wt-tree/split> tree key)

Returns a new wt-tree containing all entries of tree whose key is strictly greater than key (the entry for key itself, if present, is excluded).

Set-like operations

The following procedures combine two wt-trees based on their key sets. tree1 and tree2 must have been created with the same tree type object (e.g. both via number-wt-type, or both via the same tree type returned from make-wt-tree-type); otherwise, an error is signalled.

(wt-tree/union tree1 tree2)

Returns a new wt-tree containing all entries whose key is in tree1 or tree2 (or both). For a key present in both trees, the value from tree2 is used.

(wt-tree/union-merge tree1 tree2 merge)

Like wt-tree/union, but for a key present in both trees, the associated value is computed by calling merge with three arguments: the key, the value associated with the key in tree2, and the value associated with the key in tree1.

(wt-tree/intersection tree1 tree2)

Returns a new wt-tree containing all entries whose key is present in both tree1 and tree2. For each such key, the value from tree2 is used.

(wt-tree/difference tree1 tree2)

Returns a new wt-tree containing all entries of tree1 whose key is not present in tree2.

(wt-tree/subset? tree1 tree2)

Returns #t if the set of keys of tree1 is a subset of the set of keys of tree2, #f otherwise. Only key membership is compared; associated values are not taken into account.

(wt-tree/set-equal? tree1 tree2)

Returns #t if tree1 and tree2 have the same set of keys, #f otherwise. Just like wt-tree/subset?, only keys are compared, not values. wt-tree/set-equal? is implemented like this:

Traversal

(wt-tree/fold combiner init tree)

Combines all entries of wt-tree tree, in ascending key order, with combining function combiner, using init as the value for the smallest entry not yet part of the combined result. combiner is a procedure of three arguments, a key, its associated value, and the so-far accumulated result; it returns a new accumulated result. wt-tree/fold corresponds to a right fold over the ascending sequence of entries, i.e. it computes

for a tree with entries k₁ < k₂ < ... < kₙ. For instance, wt-tree/fold can be used to convert a wt-tree into a sorted association list:

(wt-tree/for-each proc tree)

Invokes proc once for every entry of wt-tree tree, in ascending key order, passing the key and the associated value as two arguments. The result of wt-tree/for-each is unspecified.

Last updated