liba 0.1.15

An algorithm library based on C/C++
Documentation
/*!
 @file rbt.h
 @brief red–black self-balancing binary search tree
*/

#ifndef LIBA_RBT_H
#define LIBA_RBT_H

#include "a.h"

/*!
 @ingroup liba
 @addtogroup a_rbt red–black binary search tree
 @{
*/

// clang-format off
#define A_RBT_ROOT {A_NULL}
// clang-format on

/*!
 @brief instance structure for red–black binary search tree node
*/
typedef struct a_rbt_node
{
    struct a_rbt_node *left; /*!< pointer to left child or null */
    struct a_rbt_node *right; /*!< pointer to right child or null */
    /*! pointer to parent combined with the color. The mapping is: 0 => red, 1 => black.
     The rest of the bits are the pointer to the parent node. It must be 2-byte aligned,
     and it will be null if this is the root node and therefore has no parent.
    */
#if defined(A_SIZE_POINTER) && (A_SIZE_POINTER + 0 > 1)
    a_uptr parent_;
#else /* !A_SIZE_POINTER */
    struct a_rbt_node *parent;
    unsigned int color;
#endif /* A_SIZE_POINTER */
} a_rbt_node;

/*!
 @brief access parent of red–black binary search tree node
 @param[in] node points to red–black binary search tree node
 @return a pointer to the parent of the specified red–black tree node,
 or null if it is already the root of the tree.
*/
A_INTERN a_rbt_node *a_rbt_parent(a_rbt_node const *node)
{
#if defined(A_SIZE_POINTER) && (A_SIZE_POINTER + 0 > 1)
    return a_cast_r(a_rbt_node *, node->parent_ & ~a_uptr_c(1));
#else /* !A_SIZE_POINTER */
    return node->parent;
#endif /* A_SIZE_POINTER */
}

/*!
 @brief initialize for red–black binary search tree node
 @param[in] node node to be initialized
 @param[in] parent node parent
 @return initialized node
*/
A_INTERN a_rbt_node *a_rbt_init(a_rbt_node *node, a_rbt_node *parent)
{
#if defined(A_SIZE_POINTER) && (A_SIZE_POINTER + 0 > 1)
    node->parent_ = a_cast_r(a_uptr, parent);
#else /* !A_SIZE_POINTER */
    node->parent = parent;
    node->color = 0;
#endif /* A_SIZE_POINTER */
    node->right = A_NULL;
    node->left = A_NULL;
    return node;
}

/*!
 @brief instance structure for red–black binary search tree root
*/
typedef union a_rbt
{
    struct a_rbt_node *node; //!< root node
} a_rbt;

/*!
 @brief initialize for red–black binary search tree root
 @param[in,out] root red–black binary search tree root
*/
A_INTERN void a_rbt_root(a_rbt *root) { root->node = A_NULL; }

#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */

/*!
 @brief access head node of red–black binary search tree in-order
 @param[in] root red–black binary search tree root
 @return head node or null
*/
A_EXTERN a_rbt_node *a_rbt_head(a_rbt const *root);

/*!
 @brief access tail node of red–black binary search tree in-order
 @param[in] root red–black binary search tree root
 @return tail node or null
*/
A_EXTERN a_rbt_node *a_rbt_tail(a_rbt const *root);

/*!
 @brief access next node of red–black binary search tree node in-order
 @param[in] node red–black binary search tree node
 @return next node or null
*/
A_EXTERN a_rbt_node *a_rbt_next(a_rbt_node *node);

/*!
 @brief access prev node of red–black binary search tree node in-order
 @param[in] node red–black binary search tree node
 @return prev node or null
*/
A_EXTERN a_rbt_node *a_rbt_prev(a_rbt_node *node);

/*!
 @brief access next node of red–black binary search tree node preorder
 @param[in] node red–black binary search tree node
 @return next node or null
*/
A_EXTERN a_rbt_node *a_rbt_pre_next(a_rbt_node *node);

/*!
 @brief access prev node of red–black binary search tree node preorder
 @param[in] node red–black binary search tree node
 @return prev node or null
*/
A_EXTERN a_rbt_node *a_rbt_pre_prev(a_rbt_node *node);

/*!
 @brief access head node of red–black binary search tree postorder
 @param[in] root red–black binary search tree root
 @return head node or null
*/
A_EXTERN a_rbt_node *a_rbt_post_head(a_rbt const *root);

/*!
 @brief access tail node of red–black binary search tree postorder
 @param[in] root red–black binary search tree root
 @return tail node or null
*/
A_EXTERN a_rbt_node *a_rbt_post_tail(a_rbt const *root);

/*!
 @brief access next node of red–black binary search tree node postorder
 @param[in] node red–black binary search tree node
 @return next node or null
*/
A_EXTERN a_rbt_node *a_rbt_post_next(a_rbt_node *node);

/*!
 @brief access prev node of red–black binary search tree node postorder
 @param[in] node red–black binary search tree node
 @return prev node or null
*/
A_EXTERN a_rbt_node *a_rbt_post_prev(a_rbt_node *node);

/*!
 @brief tear a node from red–black binary search tree
 @param[in] root red–black binary search tree root
 @param[in,out] next input starting node or,
 if null, root node. output next node or null.
 @return teared node or null
*/
A_EXTERN a_rbt_node *a_rbt_tear(a_rbt *root, a_rbt_node **next);

/*!
 @brief search specified content from red–black binary search tree
 @param[in] root red–black binary search tree root
 @param[in] ctx specified content
 @param[in] cmp a function that compares two nodes
  @arg cmp(lhs,rhs)==0 *lhs is equivalent to *rhs
  @arg cmp(lhs,rhs)<0 *lhs goes before *rhs
  @arg cmp(lhs,rhs)>0 *lhs goes after *rhs
 @return specified node or null
*/
A_EXTERN a_rbt_node *a_rbt_search(a_rbt const *root, void const *ctx, int (*cmp)(void const *, void const *));

/*!
 @brief insert specified node into red–black binary search tree
 @param[in] root red–black binary search tree root
 @param[in] node specified tree node
 @param[in] cmp a function that compares two nodes
  @arg cmp(lhs,rhs)==0 *lhs is equivalent to *rhs
  @arg cmp(lhs,rhs)<0 *lhs goes before *rhs
  @arg cmp(lhs,rhs)>0 *lhs goes after *rhs
 @return null or duplicate node
*/
A_EXTERN a_rbt_node *a_rbt_insert(a_rbt *root, a_rbt_node *node, int (*cmp)(void const *, void const *));

/*!
 @brief rebalance the tree after insertion of the specified node
 @param[in] root red–black binary search tree root
 @param[in] node insert tree node
*/
A_EXTERN void a_rbt_insert_adjust(a_rbt *root, a_rbt_node *node);

/*!
 @brief remove specified node from red–black binary search tree
 @param[in] root red–black binary search tree root
 @param[in] node specified tree node
*/
A_EXTERN void a_rbt_remove(a_rbt *root, a_rbt_node *node);

#if defined(__cplusplus)
} /* extern "C" */
#endif /* __cplusplus */

/*!
 @brief access the struct for this entry
 @param ptr the &a_rbt_node pointer
 @param type the type of the struct this is embedded in
 @param member the name of the a_rbt_node within the struct
*/
#define a_rbt_entry(ptr, type, member) a_container_of(ptr, type, member)

/*!
 @brief iterate over a red–black binary search tree in-order
 @code{.c}
 typedef struct
 {
     a_rbt_node node;
 } T;
 a_rbt root = A_RBT_ROOT;
 a_rbt_foreach(cur, &root)
 {
     T *it = a_rbt_entry(cur, T, node);
 }
 @endcode
 @param cur the &a_rbt_node to use as a loop counter
 @param root red–black binary search tree root
*/
#define a_rbt_foreach(cur, root) \
    for (a_rbt_node *cur = a_rbt_head(root); cur; cur = a_rbt_next(cur))

/*!
 @brief iterate over a red–black binary search tree in-order reverse
 @code{.c}
 typedef struct
 {
     a_rbt_node node;
 } T;
 a_rbt root = A_RBT_ROOT;
 a_rbt_foreach_reverse(cur, &root)
 {
     T *it = a_rbt_entry(cur, T, node);
 }
 @endcode
 @param cur the &a_rbt_node to use as a loop counter
 @param root red–black binary search tree root
*/
#define a_rbt_foreach_reverse(cur, root) \
    for (a_rbt_node *cur = a_rbt_tail(root); cur; cur = a_rbt_prev(cur))

/*!
 @brief iterate over a red–black binary search tree preorder
 @code{.c}
 typedef struct
 {
     a_rbt_node node;
 } T;
 a_rbt root = A_RBT_ROOT;
 a_rbt_pre_foreach(cur, &root)
 {
     T *it = a_rbt_entry(cur, T, node);
 }
 @endcode
 @param cur the &a_rbt_node to use as a loop counter
 @param root red–black binary search tree root
*/
#define a_rbt_pre_foreach(cur, root) \
    for (a_rbt_node *cur = (root)->node; cur; cur = a_rbt_pre_next(cur))

/*!
 @brief iterate over a red–black binary search tree preorder reverse
 @code{.c}
 typedef struct
 {
     a_rbt_node node;
 } T;
 a_rbt root = A_RBT_ROOT;
 a_rbt_pre_foreach_reverse(cur, &root)
 {
     T *it = a_rbt_entry(cur, T, node);
 }
 @endcode
 @param cur the &a_rbt_node to use as a loop counter
 @param root red–black binary search tree root
*/
#define a_rbt_pre_foreach_reverse(cur, root) \
    for (a_rbt_node *cur = (root)->node; cur; cur = a_rbt_pre_prev(cur))

/*!
 @brief iterate over a red–black binary search tree postorder
 @code{.c}
 typedef struct
 {
     a_rbt_node node;
 } T;
 a_rbt root = A_RBT_ROOT;
 a_rbt_post_foreach(cur, &root)
 {
     T *it = a_rbt_entry(cur, T, node);
 }
 @endcode
 @param cur the &a_rbt_node to use as a loop counter
 @param root red–black binary search tree root
*/
#define a_rbt_post_foreach(cur, root) \
    for (a_rbt_node *cur = a_rbt_post_head(root); cur; cur = a_rbt_post_next(cur))

/*!
 @brief iterate over a red–black binary search tree postorder reverse
 @code{.c}
 typedef struct
 {
     a_rbt_node node;
 } T;
 a_rbt root = A_RBT_ROOT;
 a_rbt_post_foreach_reverse(cur, &root)
 {
     T *it = a_rbt_entry(cur, T, node);
 }
 @endcode
 @param cur the &a_rbt_node to use as a loop counter
 @param root red–black binary search tree root
*/
#define a_rbt_post_foreach_reverse(cur, root) \
    for (a_rbt_node *cur = a_rbt_post_tail(root); cur; cur = a_rbt_post_prev(cur))

/*!
 @brief tear a red–black binary search tree using postorder traversal
 @code{.c}
 typedef struct
 {
     a_rbt_node node;
 } T;
 a_rbt root = A_AVL_ROOT;
 a_rbt_fortear(cur, next, &root)
 {
     T *it = a_rbt_entry(cur, T, node);
 }
 @endcode
 @param cur the &a_rbt_node to use as a loop counter
 @param next the &a_rbt_node to use as next node
 @param root red–black binary search tree root
*/
#define a_rbt_fortear(cur, next, root) \
    for (a_rbt_node *next = A_NULL, *cur = a_rbt_tear(root, &next); cur; cur = a_rbt_tear(root, &next))

/*! @} a_rbt */

#endif /* a/rbt.h */