rb_tree.h revision b8e80941
1b8e80941Smrg/*
2b8e80941Smrg * Copyright © 2017 Jason Ekstrand
3b8e80941Smrg *
4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
6b8e80941Smrg * to deal in the Software without restriction, including without limitation
7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
9b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
10b8e80941Smrg *
11b8e80941Smrg * The above copyright notice and this permission notice shall be included in
12b8e80941Smrg * all copies or substantial portions of the Software.
13b8e80941Smrg *
14b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17b8e80941Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20b8e80941Smrg * DEALINGS IN THE SOFTWARE.
21b8e80941Smrg */
22b8e80941Smrg
23b8e80941Smrg#ifndef RB_TREE_H
24b8e80941Smrg#define RB_TREE_H
25b8e80941Smrg
26b8e80941Smrg#include <stdbool.h>
27b8e80941Smrg#include <stddef.h>
28b8e80941Smrg#include <stdint.h>
29b8e80941Smrg#include <stdlib.h>
30b8e80941Smrg
31b8e80941Smrg/** A red-black tree node
32b8e80941Smrg *
33b8e80941Smrg * This struct represents a node in the red-black tree.  This struct should
34b8e80941Smrg * be embedded as a member in whatever structure you wish to put in the
35b8e80941Smrg * tree.
36b8e80941Smrg */
37b8e80941Smrgstruct rb_node {
38b8e80941Smrg    /** Parent and color of this node
39b8e80941Smrg     *
40b8e80941Smrg     * The least significant bit represents the color and is est to 1 for
41b8e80941Smrg     * black and 0 for red.  The other bits are the pointer to the parent
42b8e80941Smrg     * and that pointer can be retrieved by masking off the bottom bit and
43b8e80941Smrg     * casting to a pointer.
44b8e80941Smrg     */
45b8e80941Smrg    uintptr_t parent;
46b8e80941Smrg
47b8e80941Smrg    /** Left child of this node, null for a leaf */
48b8e80941Smrg    struct rb_node *left;
49b8e80941Smrg
50b8e80941Smrg    /** Right child of this node, null for a leaf */
51b8e80941Smrg    struct rb_node *right;
52b8e80941Smrg};
53b8e80941Smrg
54b8e80941Smrg/** Return the parent node of the given node or NULL if it is the root */
55b8e80941Smrgstatic inline struct rb_node *
56b8e80941Smrgrb_node_parent(struct rb_node *n)
57b8e80941Smrg{
58b8e80941Smrg    return (struct rb_node *)(n->parent & ~(uintptr_t)1);
59b8e80941Smrg}
60b8e80941Smrg
61b8e80941Smrg/** A red-black tree
62b8e80941Smrg *
63b8e80941Smrg * This struct represents the red-black tree itself.  It is just a pointer
64b8e80941Smrg * to the root node with no other metadata.
65b8e80941Smrg */
66b8e80941Smrgstruct rb_tree {
67b8e80941Smrg    struct rb_node *root;
68b8e80941Smrg};
69b8e80941Smrg
70b8e80941Smrg/** Initialize a red-black tree */
71b8e80941Smrgvoid rb_tree_init(struct rb_tree *T);
72b8e80941Smrg
73b8e80941Smrg/** Returns true if the red-black tree is empty */
74b8e80941Smrgstatic inline bool
75b8e80941Smrgrb_tree_is_empty(const struct rb_tree *T)
76b8e80941Smrg{
77b8e80941Smrg    return T->root == NULL;
78b8e80941Smrg}
79b8e80941Smrg
80b8e80941Smrg/** Retrieve the data structure containing a node
81b8e80941Smrg *
82b8e80941Smrg * \param   type    The type of the containing data structure
83b8e80941Smrg *
84b8e80941Smrg * \param   node    A pointer to a rb_node
85b8e80941Smrg *
86b8e80941Smrg * \param   field   The rb_node field in the containing data structure
87b8e80941Smrg */
88b8e80941Smrg#define rb_node_data(type, node, field) \
89b8e80941Smrg    ((type *)(((char *)(node)) - offsetof(type, field)))
90b8e80941Smrg
91b8e80941Smrg/** Insert a node into a tree at a particular location
92b8e80941Smrg *
93b8e80941Smrg * This function should probably not be used directly as it relies on the
94b8e80941Smrg * caller to ensure that the parent node is correct.  Use rb_tree_insert
95b8e80941Smrg * instead.
96b8e80941Smrg *
97b8e80941Smrg * \param   T           The red-black tree into which to insert the new node
98b8e80941Smrg *
99b8e80941Smrg * \param   parent      The node in the tree that will be the parent of the
100b8e80941Smrg *                      newly inserted node
101b8e80941Smrg *
102b8e80941Smrg * \param   node        The node to insert
103b8e80941Smrg *
104b8e80941Smrg * \param   insert_left If true, the new node will be the left child of
105b8e80941Smrg *                      \p parent, otherwise it will be the right child
106b8e80941Smrg */
107b8e80941Smrgvoid rb_tree_insert_at(struct rb_tree *T, struct rb_node *parent,
108b8e80941Smrg                       struct rb_node *node, bool insert_left);
109b8e80941Smrg
110b8e80941Smrg/** Insert a node into a tree
111b8e80941Smrg *
112b8e80941Smrg * \param   T       The red-black tree into which to insert the new node
113b8e80941Smrg *
114b8e80941Smrg * \param   node    The node to insert
115b8e80941Smrg *
116b8e80941Smrg * \param   cmp     A comparison function to use to order the nodes.
117b8e80941Smrg */
118b8e80941Smrgstatic inline void
119b8e80941Smrgrb_tree_insert(struct rb_tree *T, struct rb_node *node,
120b8e80941Smrg               int (*cmp)(const struct rb_node *, const struct rb_node *))
121b8e80941Smrg{
122b8e80941Smrg    /* This function is declared inline in the hopes that the compiler can
123b8e80941Smrg     * optimize away the comparison function pointer call.
124b8e80941Smrg     */
125b8e80941Smrg    struct rb_node *y = NULL;
126b8e80941Smrg    struct rb_node *x = T->root;
127b8e80941Smrg    bool left = false;
128b8e80941Smrg    while (x != NULL) {
129b8e80941Smrg        y = x;
130b8e80941Smrg        left = cmp(node, x) < 0;
131b8e80941Smrg        if (left)
132b8e80941Smrg            x = x->left;
133b8e80941Smrg        else
134b8e80941Smrg            x = x->right;
135b8e80941Smrg    }
136b8e80941Smrg
137b8e80941Smrg    rb_tree_insert_at(T, y, node, left);
138b8e80941Smrg}
139b8e80941Smrg
140b8e80941Smrg/** Remove a node from a tree
141b8e80941Smrg *
142b8e80941Smrg * \param   T       The red-black tree from which to remove the node
143b8e80941Smrg *
144b8e80941Smrg * \param   node    The node to remove
145b8e80941Smrg */
146b8e80941Smrgvoid rb_tree_remove(struct rb_tree *T, struct rb_node *z);
147b8e80941Smrg
148b8e80941Smrg/** Search the tree for a node
149b8e80941Smrg *
150b8e80941Smrg * If a node with a matching key exists, the first matching node found will
151b8e80941Smrg * be returned.  If no matching node exists, NULL is returned.
152b8e80941Smrg *
153b8e80941Smrg * \param   T       The red-black tree to search
154b8e80941Smrg *
155b8e80941Smrg * \param   key     The key to search for
156b8e80941Smrg *
157b8e80941Smrg * \param   cmp     A comparison function to use to order the nodes
158b8e80941Smrg */
159b8e80941Smrgstatic inline struct rb_node *
160b8e80941Smrgrb_tree_search(struct rb_tree *T, const void *key,
161b8e80941Smrg               int (*cmp)(const struct rb_node *, const void *))
162b8e80941Smrg{
163b8e80941Smrg    /* This function is declared inline in the hopes that the compiler can
164b8e80941Smrg     * optimize away the comparison function pointer call.
165b8e80941Smrg     */
166b8e80941Smrg    struct rb_node *x = T->root;
167b8e80941Smrg    while (x != NULL) {
168b8e80941Smrg        int c = cmp(x, key);
169b8e80941Smrg        if (c < 0)
170b8e80941Smrg            x = x->right;
171b8e80941Smrg        else if (c > 0)
172b8e80941Smrg            x = x->left;
173b8e80941Smrg        else
174b8e80941Smrg            return x;
175b8e80941Smrg    }
176b8e80941Smrg
177b8e80941Smrg    return x;
178b8e80941Smrg}
179b8e80941Smrg
180b8e80941Smrg/** Sloppily search the tree for a node
181b8e80941Smrg *
182b8e80941Smrg * This function searches the tree for a given node.  If a node with a
183b8e80941Smrg * matching key exists, that first matching node found will be returned.
184b8e80941Smrg * If no node with an exactly matching key exists, the node returned will
185b8e80941Smrg * be either the right-most node comparing less than \p key or the
186b8e80941Smrg * right-most node comparing greater than \p key.  If the tree is empty,
187b8e80941Smrg * NULL is returned.
188b8e80941Smrg *
189b8e80941Smrg * \param   T       The red-black tree to search
190b8e80941Smrg *
191b8e80941Smrg * \param   key     The key to search for
192b8e80941Smrg *
193b8e80941Smrg * \param   cmp     A comparison function to use to order the nodes
194b8e80941Smrg */
195b8e80941Smrgstatic inline struct rb_node *
196b8e80941Smrgrb_tree_search_sloppy(struct rb_tree *T, const void *key,
197b8e80941Smrg                      int (*cmp)(const struct rb_node *, const void *))
198b8e80941Smrg{
199b8e80941Smrg    /* This function is declared inline in the hopes that the compiler can
200b8e80941Smrg     * optimize away the comparison function pointer call.
201b8e80941Smrg     */
202b8e80941Smrg    struct rb_node *y = NULL;
203b8e80941Smrg    struct rb_node *x = T->root;
204b8e80941Smrg    while (x != NULL) {
205b8e80941Smrg        y = x;
206b8e80941Smrg        int c = cmp(x, key);
207b8e80941Smrg        if (c < 0)
208b8e80941Smrg            x = x->right;
209b8e80941Smrg        else if (c > 0)
210b8e80941Smrg            x = x->left;
211b8e80941Smrg        else
212b8e80941Smrg            return x;
213b8e80941Smrg    }
214b8e80941Smrg
215b8e80941Smrg    return y;
216b8e80941Smrg}
217b8e80941Smrg
218b8e80941Smrg/** Get the first (left-most) node in the tree or NULL */
219b8e80941Smrgstruct rb_node *rb_tree_first(struct rb_tree *T);
220b8e80941Smrg
221b8e80941Smrg/** Get the last (right-most) node in the tree or NULL */
222b8e80941Smrgstruct rb_node *rb_tree_last(struct rb_tree *T);
223b8e80941Smrg
224b8e80941Smrg/** Get the next node (to the right) in the tree or NULL */
225b8e80941Smrgstruct rb_node *rb_node_next(struct rb_node *node);
226b8e80941Smrg
227b8e80941Smrg/** Get the next previous (to the left) in the tree or NULL */
228b8e80941Smrgstruct rb_node *rb_node_prev(struct rb_node *node);
229b8e80941Smrg
230b8e80941Smrg/** Get the next node if available or the same node again.
231b8e80941Smrg *
232b8e80941Smrg * \param   type    The type of the containing data structure
233b8e80941Smrg *
234b8e80941Smrg * \param   node    The variable name for current node in the iteration;
235b8e80941Smrg *                  this will be declared as a pointer to \p type
236b8e80941Smrg *
237b8e80941Smrg * \param   field   The rb_node field in containing data structure
238b8e80941Smrg */
239b8e80941Smrg#define rb_tree_node_next_if_available(type, node, field) \
240b8e80941Smrg   (&node->field != NULL) ? rb_node_data(type, rb_node_next(&node->field), field) : node
241b8e80941Smrg
242b8e80941Smrg/** Get the previous node if available or the same node again.
243b8e80941Smrg *
244b8e80941Smrg * \param   type    The type of the containing data structure
245b8e80941Smrg *
246b8e80941Smrg * \param   node    The variable name for current node in the iteration;
247b8e80941Smrg *                  this will be declared as a pointer to \p type
248b8e80941Smrg *
249b8e80941Smrg * \param   field   The rb_node field in containing data structure
250b8e80941Smrg */
251b8e80941Smrg#define rb_tree_node_prev_if_available(type, node, field) \
252b8e80941Smrg   (&node->field != NULL) ? rb_node_data(type, rb_node_prev(&node->field), field) : node
253b8e80941Smrg
254b8e80941Smrg/** Iterate over the nodes in the tree
255b8e80941Smrg *
256b8e80941Smrg * \param   type    The type of the containing data structure
257b8e80941Smrg *
258b8e80941Smrg * \param   node    The variable name for current node in the iteration;
259b8e80941Smrg *                  this will be declared as a pointer to \p type
260b8e80941Smrg *
261b8e80941Smrg * \param   T       The red-black tree
262b8e80941Smrg *
263b8e80941Smrg * \param   field   The rb_node field in containing data structure
264b8e80941Smrg */
265b8e80941Smrg#define rb_tree_foreach(type, node, T, field) \
266b8e80941Smrg   for (type *node = rb_node_data(type, rb_tree_first(T), field); \
267b8e80941Smrg        &node->field != NULL; \
268b8e80941Smrg        node = rb_node_data(type, rb_node_next(&node->field), field))
269b8e80941Smrg
270b8e80941Smrg/** Iterate over the nodes in the tree, allowing the current node to be freed
271b8e80941Smrg *
272b8e80941Smrg * \param   type    The type of the containing data structure
273b8e80941Smrg *
274b8e80941Smrg * \param   node    The variable name for current node in the iteration;
275b8e80941Smrg *                  this will be declared as a pointer to \p type
276b8e80941Smrg *
277b8e80941Smrg * \param   T       The red-black tree
278b8e80941Smrg *
279b8e80941Smrg * \param   field   The rb_node field in containing data structure
280b8e80941Smrg */
281b8e80941Smrg#define rb_tree_foreach_safe(type, node, T, field) \
282b8e80941Smrg   for (type *node = rb_node_data(type, rb_tree_first(T), field), \
283b8e80941Smrg           *__next = rb_tree_node_next_if_available(type, node, field); \
284b8e80941Smrg        &node->field != NULL; \
285b8e80941Smrg        node = __next, __next = rb_tree_node_next_if_available(type, node, field))
286b8e80941Smrg
287b8e80941Smrg/** Iterate over the nodes in the tree in reverse
288b8e80941Smrg *
289b8e80941Smrg * \param   type    The type of the containing data structure
290b8e80941Smrg *
291b8e80941Smrg * \param   node    The variable name for current node in the iteration;
292b8e80941Smrg *                  this will be declared as a pointer to \p type
293b8e80941Smrg *
294b8e80941Smrg * \param   T       The red-black tree
295b8e80941Smrg *
296b8e80941Smrg * \param   field   The rb_node field in containing data structure
297b8e80941Smrg */
298b8e80941Smrg#define rb_tree_foreach_rev(type, node, T, field) \
299b8e80941Smrg   for (type *node = rb_node_data(type, rb_tree_last(T), field); \
300b8e80941Smrg        &node->field != NULL; \
301b8e80941Smrg        node = rb_node_data(type, rb_node_prev(&node->field), field))
302b8e80941Smrg
303b8e80941Smrg/** Iterate over the nodes in the tree in reverse, allowing the current node to be freed
304b8e80941Smrg *
305b8e80941Smrg * \param   type    The type of the containing data structure
306b8e80941Smrg *
307b8e80941Smrg * \param   node    The variable name for current node in the iteration;
308b8e80941Smrg *                  this will be declared as a pointer to \p type
309b8e80941Smrg *
310b8e80941Smrg * \param   T       The red-black tree
311b8e80941Smrg *
312b8e80941Smrg * \param   field   The rb_node field in containing data structure
313b8e80941Smrg */
314b8e80941Smrg#define rb_tree_foreach_rev_safe(type, node, T, field) \
315b8e80941Smrg   for (type *node = rb_node_data(type, rb_tree_last(T), field), \
316b8e80941Smrg           *__prev = rb_tree_node_prev_if_available(type, node, field);  \
317b8e80941Smrg        &node->field != NULL; \
318b8e80941Smrg        node = __prev, __prev = rb_tree_node_prev_if_available(type, node, field))
319b8e80941Smrg
320b8e80941Smrg/** Validate a red-black tree
321b8e80941Smrg *
322b8e80941Smrg * This function walks the tree and validates that this is a valid red-
323b8e80941Smrg * black tree.  If anything is wrong, it will assert-fail.
324b8e80941Smrg */
325b8e80941Smrgvoid rb_tree_validate(struct rb_tree *T);
326b8e80941Smrg
327b8e80941Smrg#endif /* RB_TREE_H */
328