Trees - osvaldoandrade/ova-lib GitHub Wiki

Trees

Read this page when key order is part of the problem. The tree module is the right tool when you need search by key plus ordered operations such as minimum, maximum, predecessor, successor, range query, or in-order traversal.

Constructor and Variants

The constructor is:

tree *create_tree(tree_type type, comparator cmp);

The 2 variants are:

Variant Meaning
TREE_AVL AVL tree
TREE_RED_BLACK red-black tree

The public API and ownership rules are the same for both variants. The variant choice changes balancing strategy, not the caller contract.

Core API

Function Meaning
insert inserts or updates one key-value pair
search returns the stored value for a key or NULL
delete removes one key if present
min returns the value at the smallest key
max returns the value at the largest key
predecessor returns the value at the greatest key smaller than the query
successor returns the value at the smallest key larger than the query
range_query returns an allocated list of values in inclusive key range order
in_order_traverse visits (key, value) pairs in ascending key order
size returns the current pair count
free frees tree nodes and the tree object

Insert and Update Semantics

The comparator defines key equality.

When insert sees a new key, it stores the key pointer and the value pointer.

When insert sees a key that compares equal to an existing key, it updates the stored value pointer and keeps the original stored key pointer. The new key pointer passed to the second insertion is not stored.

Return Shapes Matter

The tree API returns values, not keys, from:

search

min

max

predecessor

successor

That means if the caller needs both the key and the value, in_order_traverse is the public path that exposes both together.

Range Query and Traversal

t->range_query(t, low, high) returns an allocated list container of values whose keys lie in the inclusive range [low, high].

The values in that list are ordered by key. The values are stored pointers, not copies.

The caller must free the list container with list->free. The caller must not free list elements unless the program owns those payload objects for independent reasons.

Missing-Key Behavior

search returns NULL for a missing key.

delete on a missing key is a no-op.

predecessor and successor work even when the queried key is not stored. They search the order position that the query key would occupy and return the neighboring stored value.

Ownership and Cleanup

The tree owns nodes only. It does not own user keys or user values.

Destroy the tree with t->free(t). Destroy range-result lists with list->free.

Read Next

If the problem is uniqueness without attached values, move to Sets. If the problem is prefix search over strings, move to Trie.