|
| 1 | +/* |
| 2 | + * Copyright (c) 2018 Intel Corporation |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: Apache-2.0 |
| 5 | + */ |
| 6 | + |
| 7 | +/** |
| 8 | + * @file |
| 9 | + * @brief Red/Black balanced tree data structure |
| 10 | + * |
| 11 | + * This implements an intrusive balanced tree that guarantees |
| 12 | + * O(log2(N)) runtime for all operations and amortized O(1) behavior |
| 13 | + * for creation and destruction of whole trees. The algorithms and |
| 14 | + * naming are conventional per existing academic and didactic |
| 15 | + * implementations, c.f.: |
| 16 | + * |
| 17 | + * https://en.wikipedia.org/wiki/Red%E2%80%93black_tree |
| 18 | + * |
| 19 | + * The implementation is size-optimized to prioritize runtime memory |
| 20 | + * usage. The data structure is intrusive, which is to say the struct |
| 21 | + * rbnode handle is intended to be placed in a separate struct the |
| 22 | + * same way other such structures (e.g. Zephyr's dlist list) and |
| 23 | + * requires no data pointer to be stored in the node. The color bit |
| 24 | + * is unioned with a pointer (fairly common for such libraries). Most |
| 25 | + * notably, there is no "parent" pointer stored in the node, the upper |
| 26 | + * structure of the tree being generated dynamically via a stack as |
| 27 | + * the tree is recursed. So the overall memory overhead of a node is |
| 28 | + * just two pointers, identical with a doubly-linked list. |
| 29 | + */ |
| 30 | + |
| 31 | +#ifndef _RB_H |
| 32 | +#define _RB_H |
| 33 | + |
| 34 | +struct rbnode { |
| 35 | + struct rbnode *children[2]; |
| 36 | +}; |
| 37 | + |
| 38 | +/** |
| 39 | + * @typedef rb_lessthan_t |
| 40 | + * @brief Red/black tree comparison predicate |
| 41 | + * |
| 42 | + * Compares the two nodes and returns 1 if node A is strictly less |
| 43 | + * than B according to the tree's sorting criteria, 0 otherwise. |
| 44 | + */ |
| 45 | +typedef int (*rb_lessthan_t)(struct rbnode *a, struct rbnode *b); |
| 46 | + |
| 47 | +struct rbtree { |
| 48 | + struct rbnode *root; |
| 49 | + rb_lessthan_t lessthan_fn; |
| 50 | + int max_depth; |
| 51 | +}; |
| 52 | + |
| 53 | +typedef void (*rb_visit_t)(struct rbnode *node, void *cookie); |
| 54 | + |
| 55 | +struct rbnode *_rb_child(struct rbnode *node, int side); |
| 56 | +int _rb_is_black(struct rbnode *node); |
| 57 | +void _rb_walk(struct rbnode *node, rb_visit_t visit_fn, void *cookie); |
| 58 | +struct rbnode *_rb_get_minmax(struct rbtree *tree, int side); |
| 59 | + |
| 60 | +/** |
| 61 | + * @brief Insert node into tree |
| 62 | + */ |
| 63 | +void rb_insert(struct rbtree *tree, struct rbnode *node); |
| 64 | + |
| 65 | +/** |
| 66 | + * @brief Remove node from tree |
| 67 | + */ |
| 68 | +void rb_remove(struct rbtree *tree, struct rbnode *node); |
| 69 | + |
| 70 | +/** |
| 71 | + * @brief Returns the lowest-sorted member of the tree |
| 72 | + */ |
| 73 | +static inline struct rbnode *rb_get_min(struct rbtree *tree) |
| 74 | +{ |
| 75 | + return _rb_get_minmax(tree, 0); |
| 76 | +} |
| 77 | + |
| 78 | +/** |
| 79 | + * @brief Returns the highest-sorted member of the tree |
| 80 | + */ |
| 81 | +static inline struct rbnode *rb_get_max(struct rbtree *tree) |
| 82 | +{ |
| 83 | + return _rb_get_minmax(tree, 1); |
| 84 | +} |
| 85 | + |
| 86 | +/** |
| 87 | + * @brief Walk/enumerate a rbtree |
| 88 | + * |
| 89 | + * Very simple recursive enumeration implementation. A rather more |
| 90 | + * subtle (have to alloca() a stack to manage manually) iterative one |
| 91 | + * is possible that uses a FOREACH-style macro API, but this is good |
| 92 | + * enough for many purposes and much smaller. |
| 93 | + */ |
| 94 | +static inline void rb_walk(struct rbtree *tree, rb_visit_t visit_fn, |
| 95 | + void *cookie) |
| 96 | +{ |
| 97 | + _rb_walk(tree->root, visit_fn, cookie); |
| 98 | +} |
| 99 | + |
| 100 | +#endif /* _RB_H */ |
0 commit comments