/* * Copyright (c) 2018 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief Red/Black balanced tree data structure * * This implements an intrusive balanced tree that guarantees * O(log2(N)) runtime for all operations and amortized O(1) behavior * for creation and destruction of whole trees. The algorithms and * naming are conventional per existing academic and didactic * implementations, c.f.: * * https://en.wikipedia.org/wiki/Red%E2%80%93black_tree * * The implementation is size-optimized to prioritize runtime memory * usage. The data structure is intrusive, which is to say the struct * rbnode handle is intended to be placed in a separate struct the * same way other such structures (e.g. Zephyr's dlist list) and * requires no data pointer to be stored in the node. The color bit * is unioned with a pointer (fairly common for such libraries). Most * notably, there is no "parent" pointer stored in the node, the upper * structure of the tree being generated dynamically via a stack as * the tree is recursed. So the overall memory overhead of a node is * just two pointers, identical with a doubly-linked list. */ #ifndef _RB_H #define _RB_H struct rbnode { struct rbnode *children[2]; }; /** * @typedef rb_lessthan_t * @brief Red/black tree comparison predicate * * Compares the two nodes and returns 1 if node A is strictly less * than B according to the tree's sorting criteria, 0 otherwise. */ typedef int (*rb_lessthan_t)(struct rbnode *a, struct rbnode *b); struct rbtree { struct rbnode *root; rb_lessthan_t lessthan_fn; int max_depth; }; typedef void (*rb_visit_t)(struct rbnode *node, void *cookie); struct rbnode *_rb_child(struct rbnode *node, int side); int _rb_is_black(struct rbnode *node); void _rb_walk(struct rbnode *node, rb_visit_t visit_fn, void *cookie); struct rbnode *_rb_get_minmax(struct rbtree *tree, int side); /** * @brief Insert node into tree */ void rb_insert(struct rbtree *tree, struct rbnode *node); /** * @brief Remove node from tree */ void rb_remove(struct rbtree *tree, struct rbnode *node); /** * @brief Returns the lowest-sorted member of the tree */ static inline struct rbnode *rb_get_min(struct rbtree *tree) { return _rb_get_minmax(tree, 0); } /** * @brief Returns the highest-sorted member of the tree */ static inline struct rbnode *rb_get_max(struct rbtree *tree) { return _rb_get_minmax(tree, 1); } /** * @brief Returns true if the given node is part of the tree * * Note that this does not internally dereference the node pointer * (though the tree's lessthan callback might!), it just tests it for * equality with items in the tree. So it's feasible to use this to * implement a "set" construct by simply testing the pointer value * itself. */ int rb_contains(struct rbtree *tree, struct rbnode *node); /** * @brief Walk/enumerate a rbtree * * Very simple recursive enumeration implementation. A rather more * subtle (have to alloca() a stack to manage manually) iterative one * is possible that uses a FOREACH-style macro API, but this is good * enough for many purposes and much smaller. */ static inline void rb_walk(struct rbtree *tree, rb_visit_t visit_fn, void *cookie) { _rb_walk(tree->root, visit_fn, cookie); } #endif /* _RB_H */