1.. _rbtree_api:
2
3Balanced Red/Black Tree
4=======================
5
6For circumstances where sorted containers may become large at runtime,
7a list becomes problematic due to algorithmic costs of searching it.
8For these situations, Zephyr provides a balanced tree implementation
9which has runtimes on search and removal operations bounded at
10O(log2(N)) for a tree of size N.  This is implemented using a
11conventional red/black tree as described by multiple academic sources.
12
13The :c:struct:`rbtree` tracking struct for a rbtree may be initialized
14anywhere in user accessible memory.  It should contain only zero bits
15before first use.  No specific initialization API is needed or
16required.
17
18Unlike a list, where position is explicit, the ordering of nodes
19within an rbtree must be provided as a predicate function by the user.
20A function of type :c:func:`rb_lessthan_t` should be assigned to the
21``lessthan_fn`` field of the :c:struct:`rbtree` struct before any tree
22operations are attempted.  This function should, as its name suggests,
23return a boolean True value if the first node argument is "less than"
24the second in the ordering desired by the tree.  Note that "equal" is
25not allowed, nodes within a tree must have a single fixed order for
26the algorithm to work correctly.
27
28As with the slist and dlist containers, nodes within an rbtree are
29represented as a :c:struct:`rbnode` structure which exists in
30user-managed memory, typically embedded within the data structure
31being tracked in the tree.  Unlike the list code, the data within an
32rbnode is entirely opaque.  It is not possible for the user to extract
33the binary tree topology and "manually" traverse the tree as it is for
34a list.
35
36Nodes can be inserted into a tree with :c:func:`rb_insert` and removed
37with :c:func:`rb_remove`.  Access to the "first" and "last" nodes within a
38tree (in the sense of the order defined by the comparison function) is
39provided by :c:func:`rb_get_min` and :c:func:`rb_get_max`.  There is also a
40predicate, :c:func:`rb_contains`, which returns a boolean True if the
41provided node pointer exists as an element within the tree.  As
42described above, all of these routines are guaranteed to have at most
43log time complexity in the size of the tree.
44
45There are two mechanisms provided for enumerating all elements in an
46rbtree.  The first, :c:func:`rb_walk`, is a simple callback implementation
47where the caller specifies a C function pointer and an untyped
48argument to be passed to it, and the tree code calls that function for
49each node in order.  This has the advantage of a very simple
50implementation, at the cost of a somewhat more cumbersome API for the
51user (not unlike ISO C's :c:func:`bsearch` routine).  It is a recursive
52implementation, however, and is thus not always available in
53environments that forbid the use of unbounded stack techniques like
54recursion.
55
56There is also a :c:macro:`RB_FOR_EACH` iterator provided, which, like the
57similar APIs for the lists, works to iterate over a list in a more
58natural way, using a nested code block instead of a callback.  It is
59also nonrecursive, though it requires log-sized space on the stack by
60default (however, this can be configured to use a fixed/maximally size
61buffer instead where needed to avoid the dynamic allocation).  As with
62the lists, this is also available in a :c:macro:`RB_FOR_EACH_CONTAINER`
63variant which enumerates using a pointer to a container field and not
64the raw node pointer.
65
66Tree Internals
67--------------
68
69As described, the Zephyr rbtree implementation is a conventional
70red/black tree as described pervasively in academic sources.  Low
71level details about the algorithm are out of scope for this document,
72as they match existing conventions.  This discussion will be limited
73to details notable or specific to the Zephyr implementation.
74
75The core invariant guaranteed by the tree is that the path from the root of
76the tree to any leaf is no more than twice as long as the path to any
77other leaf.  This is achieved by associating one bit of "color" with
78each node, either red or black, and enforcing a rule that no red child
79can be a child of another red child (i.e. that the number of black
80nodes on any path to the root must be the same, and that no more than
81that number of "extra" red nodes may be present).  This rule is
82enforced by a set of rotation rules used to "fix" trees following
83modification.
84
85.. figure:: rbtree.png
86    :align: center
87    :alt: rbtree example
88    :figclass: align-center
89
90    A maximally unbalanced rbtree with a black height of two.  No more
91    nodes can be added underneath the rightmost node without
92    rebalancing.
93
94These rotations are conceptually implemented on top of a primitive
95that "swaps" the position of one node with another in the list.
96Typical implementations effect this by simply swapping the nodes
97internal "data" pointers, but because the Zephyr :c:struct:`rbnode` is
98intrusive, that cannot work.  Zephyr must include somewhat more
99elaborate code to handle the edge cases (for example, one swapped node
100can be the root, or the two may already be parent/child).
101
102The :c:struct:`rbnode` struct for a Zephyr rbtree contains only two
103pointers, representing the "left", and "right" children of a node
104within the binary tree.  Traversal of a tree for rebalancing following
105modification, however, routinely requires the ability to iterate
106"upwards" from a node as well.  It is very common for red/black trees
107in the industry to store a third "parent" pointer for this purpose.
108Zephyr avoids this requirement by building a "stack" of node pointers
109locally as it traverses downward through the tree and updating it
110appropriately as modifications are made.  So a Zephyr rbtree can be
111implemented with no more runtime storage overhead than a dlist.
112
113These properties, of a balanced tree data structure that works with
114only two pointers of data per node and that works without any need for
115a memory allocation API, are quite rare in the industry and are
116somewhat unique to Zephyr.
117
118Red/Black Tree API Reference
119--------------------------------
120
121.. doxygengroup:: rbtree_apis
122