libcstl
Loading...
Searching...
No Matches
bintree.h
Go to the documentation of this file.
1/*!
2 * @file
3 */
4
5#ifndef CSTL_BINTREE_H
6#define CSTL_BINTREE_H
7
8/*!
9 * @defgroup bintrees Binary trees
10 * @ingroup lowlevel
11 * @brief Objects implemented as binary trees
12 */
13
14/*!
15 * @defgroup bintree Binary tree
16 * @ingroup bintrees
17 * @brief An unbalanced binary tree
18 */
19/*!
20 * @addtogroup bintree
21 * @{
22 */
23
24#include "cstl/common.h"
25
26#include <stddef.h>
27
28/*!
29 * @brief Node to anchor an element within a binary tree
30 *
31 * Users of the binary tree object declare this object within another
32 * object as follows:
33 * @code{.c}
34 * struct object {
35 * ...
36 * struct cstl_bintree_node tree_node;
37 * ...
38 * };
39 * @endcode
40 *
41 * When calling cstl_bintree_init(), the caller passes the offset of
42 * @p tree_node within their object as the @p off parameter of that
43 * function, e.g.
44 * @code{.c}
45 * offsetof(struct object, tree_node)
46 * @endcode
47 */
49{
50 /*! @privatesection */
51 struct cstl_bintree_node * p, * l, * r;
52};
53
54/*!
55 * @brief Binary tree object
56 *
57 * Callers declare or allocate an object of this type to instantiate
58 * a binary tree. Users are encouraged to declare (and initialize) this
59 * object with the DECLARE_CSTL_BINTREE() macro. Any other declaration or
60 * allocation must be initialized via cstl_bintree_init().
61 */
63{
64 /*! @privatesection */
65 struct cstl_bintree_node * root;
66 size_t size;
67
68 size_t off;
69 struct
70 {
71 /*! @privatesection */
73 void * priv;
74 } cmp;
75};
76
77/*!
78 * @brief Constant initialization of a cstl_bintree object
79 *
80 * @param TYPE The type of object that the tree will hold
81 * @param MEMB The name of the @p cstl_bintree_node member within @p TYPE.
82 * @param CMP A pointer to a function of type @p cstl_compare_func_t that
83 * will be used to compare elements in the tree
84 * @param PRIV A pointer to a private data structure that will be passed
85 * to calls to the @p CMP function
86 *
87 * @see cstl_bintree_node for a description of the relationship between
88 * @p TYPE and @p MEMB
89 */
90#define CSTL_BINTREE_INITIALIZER(TYPE, MEMB, CMP, PRIV) \
91 { \
92 .root = NULL, \
93 .size = 0, \
94 .off = offsetof(TYPE, MEMB), \
95 .cmp = { \
96 .func = CMP, \
97 .priv = PRIV \
98 } \
99 }
100/*!
101 * @brief (Statically) declare and initialize a binary tree
102 *
103 * @param NAME The name of the variable being declared
104 * @param TYPE The type of object that the tree will hold
105 * @param MEMB The name of the @p cstl_bintree_node member within @p TYPE.
106 * @param CMP A pointer to a function of type @p cstl_compare_func_t that
107 * will be used to compare elements in the tree
108 * @param PRIV A pointer to a private data structure that will be passed
109 * to calls to the @p CMP function
110 *
111 * @see cstl_bintree_node for a description of the relationship between
112 * @p TYPE and @p MEMB
113 */
114#define DECLARE_CSTL_BINTREE(NAME, TYPE, MEMB, CMP, PRIV) \
115 struct cstl_bintree NAME = \
116 CSTL_BINTREE_INITIALIZER(TYPE, MEMB, CMP, PRIV)
117
118/*!
119 * @brief Initialize a binary tree object
120 *
121 * @param[in,out] bt A pointer to the object to be initialized
122 * @param[in] cmp A function that can compare objects in the tree
123 * @param[in] priv A pointer to private data that will be
124 * passed to the @p cmp function
125 * @param[in] off The offset of the @p cstl_bintree_node object within the
126 * object(s) that will be stored in the tree
127 */
128static inline void cstl_bintree_init(struct cstl_bintree * const bt,
129 cstl_compare_func_t * const cmp,
130 void * const priv,
131 const size_t off)
132{
133 bt->root = NULL;
134 bt->size = 0;
135
136 bt->off = off;
137
138 bt->cmp.func = cmp;
139 bt->cmp.priv = priv;
140}
141
142/*!
143 * @brief Get the number of objects in the tree
144 *
145 * @param[in] bt A pointer to the binary tree
146 *
147 * @return The number of objects in the tree
148 */
149static inline size_t cstl_bintree_size(const struct cstl_bintree * const bt)
150{
151 return bt->size;
152}
153
154/*!
155 * @brief Insert a new object into the tree
156 *
157 * @param[in] bt A pointer to the binary tree
158 * @param[in] e A pointer to the object to be inserted
159 * @param[in] p A pointer to the parent of the object to be inserted.
160 * This pointer may be NULL or can be found via
161 * cstl_bintree_find()
162 *
163 * The inserted object does not need to compare as unequal to any/all
164 * other objects already in the tree. If the object is equal to one or
165 * more objects already in the tree, it is up to the caller to distinguish
166 * between them during a find or erase operation.
167 *
168 * The inserted object must not be modified (in such a way as to affect
169 * its comparison with other objects in the tree) as that modification
170 * can cause the assumptions about the ordering of elements within the
171 * tree to become invalid and lead to undefined behavior.
172 */
173void cstl_bintree_insert(struct cstl_bintree * bt, void * e, void * p);
174
175/*!
176 * @brief Find an element within a tree
177 *
178 * @param[in] bt A pointer to the binary tree
179 * @param[in] e A pointer to an object to compare to those in the tree
180 * @param[out] p The location in which to return a pointer to the parent
181 * of the found element (or where it would be located). This
182 * pointer may be NULL
183 *
184 * The tree will be searched for an element that compares as equal
185 * to the @p e parameter as defined by the @p cmp function provided
186 * when the tree was initialized.
187 *
188 * @return A pointer to the (first) object in the tree that matches
189 * @retval NULL No matching object was found
190 */
191const void * cstl_bintree_find(
192 const struct cstl_bintree * bt, const void * e, const void ** p);
193
194/*!
195 * @brief Remove an element from the tree
196 *
197 * @param[in] bt A pointer to the binary tree
198 * @param[in] e A pointer to an object to compare to those in the tree
199 *
200 * The tree will be searched for an element that compares as equal
201 * to the @p e parameter as defined by the @p cmp function provided
202 * when the tree was initialized. The first element found that matches
203 * will be removed from the tree, and a pointer to that element will
204 * be returned.
205 *
206 * @return A pointer to the removed element
207 * @retval NULL No element was found/removed
208 */
209void * cstl_bintree_erase(struct cstl_bintree * bt, const void * e);
210
211/*!
212 * @brief Remove all elements from the tree
213 *
214 * @param[in] bt A pointer to the binary tree
215 * @param[in] clr A pointer to a function to be called for each
216 * element in the tree
217 * @param[in] priv A pointer to be passed to each invocation of @p clr
218 *
219 * All elements are removed from the tree and the @p clr function is
220 * called for each element that was in the tree. The order in which
221 * the elements are removed and @p clr is called is not specified, but
222 * the callee may take ownership of an element at the time that @p clr
223 * is called for that element and not before.
224 *
225 * Upon return from this function, the tree contains no elements, and
226 * is as it was immediately after being initialized. No further operations
227 * on the tree are necessary to make it ready to go out of scope or be
228 * destroyed.
229 */
230void cstl_bintree_clear(struct cstl_bintree * bt,
231 cstl_xtor_func_t * clr, void * priv);
232
233/*!
234 * @brief Swap the tree objects at the two given locations
235 *
236 * @param[in,out] a A pointer to a binary tree
237 * @param[in,out] b A pointer to a(nother) binary tree
238 *
239 * The trees at the given locations will be swapped such that upon return,
240 * @p a will contain the tree previously pointed to by @p b and vice versa.
241 */
242void cstl_bintree_swap(struct cstl_bintree * a, struct cstl_bintree * b);
243
244/*!
245 * @brief Enumeration indicating the order in which a tree
246 * element is being visited during @p cstl_bintree_foreach()
247 */
248typedef enum
249{
250 /*! @brief The first visit to an element that has at least one child */
252 /*!
253 * @brief The second visit to an element, after its
254 * first child has/would have been visited
255 */
257 /*!
258 * @brief The last visit to an element, after both
259 * children have/would have been visited
260 */
262 /*! @brief The only visit to an element that has no children */
265
266/*!
267 * @brief Enumeration indicating the order in which elements
268 * in a tree are visited during @p cstl_bintree_foreach()
269 *
270 * @note The enumerations and their descriptions assume that the
271 * tree's associated @p cmp function compares elements in the
272 * "normal/expected" fashion
273 */
274typedef enum
275{
276 /*! @brief Each element in the tree is visited from left-to-right */
278 /*! @brief Each element in the tree is visited from right-to-left */
281
282/*!
283 * @brief The type of @a visit function associated with cstl_bintree_foreach()
284 *
285 * The @p cstl_bintree_foreach() function requires that visited elements are
286 * presented as @a const because modifying the element could cause the
287 * previously determined (in)equality relationships between elements to
288 * be modified and for future operations on the tree to result in
289 * undefined behavior
290 *
291 * @param[in] e A pointer to the element being visited
292 * @param[in] ord An enumeration indicating which visit
293 * to this element is being performed
294 * @param[in] p A pointer to a private data object belonging to the callee
295 *
296 * @retval 0 Continue visiting elements in the tree
297 * @retval Nonzero Stop visiting elements in the tree
298 */
300 const void * e, cstl_bintree_visit_order_t ord, void * p);
301
302/*!
303 * @brief Visit each element in a tree, calling a user-defined
304 * function for each visit
305 *
306 * @param[in] bt A pointer to the binary tree
307 * @param[in] visit A pointer to a function to be called for each visit
308 * @param[in] priv A pointer to a private data structure that will be passed
309 * to each call to @p visit
310 * @param[in] dir The direction in which to traverse the tree
311 *
312 * The function continues visiting elements in the tree so long as the
313 * given @p visit function returns 0. If the @p visit function returns a
314 * non-zero value, no more elements are visited, and the function returns
315 * the non-zero value that halted visitations.
316 *
317 * @see cstl_bintree_visit_order_t
318 */
319int cstl_bintree_foreach(const struct cstl_bintree * bt,
320 cstl_bintree_const_visit_func_t * visit, void * priv,
322
323/*!
324 * @brief Determine the maximum and minimum heights of a tree
325 *
326 * @param[in] bt A pointer to the binary tree
327 * @param[out] min The length of the shortest path from a root to a leaf
328 * @param[out] max The length of the longest path from the root to a leaf
329 */
330void cstl_bintree_height(const struct cstl_bintree * bt,
331 size_t * min, size_t * max);
332
333/*! @private */
334int __cstl_bintree_cmp(const struct cstl_bintree *,
335 const struct cstl_bintree_node *,
336 const struct cstl_bintree_node *);
337
338/*! @private */
339const struct cstl_bintree_node * __cstl_bintree_erase(
340 struct cstl_bintree *, struct cstl_bintree_node *);
341
342/*! @private */
343typedef struct cstl_bintree_node ** (__cstl_bintree_child_func_t)(
344 struct cstl_bintree_node *);
345
346/*! @private */
347static inline
348struct cstl_bintree_node ** __cstl_bintree_left(
349 struct cstl_bintree_node * const n)
350{
351 return &n->l;
352}
353
354/*! @private */
355static inline
356struct cstl_bintree_node ** __cstl_bintree_right(
357 struct cstl_bintree_node * const n)
358{
359 return &n->r;
360}
361
362/*! @private */
363void __cstl_bintree_rotate(struct cstl_bintree *,
364 struct cstl_bintree_node *,
365 __cstl_bintree_child_func_t *,
366 __cstl_bintree_child_func_t *);
367
368/*!
369 * @}
370 */
371
372#endif
void cstl_xtor_func_t(void *obj, void *priv)
Type for functions called to construct, clear, or destroy an object.
Definition common.h:97
int cstl_compare_func_t(const void *obj1, const void *obj2, void *priv)
Function type for comparing (in)equality of two objects.
Definition common.h:49
void cstl_bintree_insert(struct cstl_bintree *bt, void *e, void *p)
Insert a new object into the tree.
Definition bintree.c:63
cstl_bintree_visit_order_t
Enumeration indicating the order in which a tree element is being visited during cstl_bintree_foreach...
Definition bintree.h:249
static size_t cstl_bintree_size(const struct cstl_bintree *const bt)
Get the number of objects in the tree.
Definition bintree.h:149
static void cstl_bintree_init(struct cstl_bintree *const bt, cstl_compare_func_t *const cmp, void *const priv, const size_t off)
Initialize a binary tree object.
Definition bintree.h:128
cstl_bintree_foreach_dir_t
Enumeration indicating the order in which elements in a tree are visited during cstl_bintree_foreach(...
Definition bintree.h:275
int cstl_bintree_const_visit_func_t(const void *e, cstl_bintree_visit_order_t ord, void *p)
The type of visit function associated with cstl_bintree_foreach()
Definition bintree.h:299
void cstl_bintree_height(const struct cstl_bintree *bt, size_t *min, size_t *max)
Determine the maximum and minimum heights of a tree.
Definition bintree.c:608
int cstl_bintree_foreach(const struct cstl_bintree *bt, cstl_bintree_const_visit_func_t *visit, void *priv, cstl_bintree_foreach_dir_t dir)
Visit each element in a tree, calling a user-defined function for each visit.
Definition bintree.c:475
const void * cstl_bintree_find(const struct cstl_bintree *bt, const void *e, const void **p)
Find an element within a tree.
Definition bintree.c:93
void cstl_bintree_swap(struct cstl_bintree *a, struct cstl_bintree *b)
Swap the tree objects at the two given locations.
Definition bintree.c:506
void * cstl_bintree_erase(struct cstl_bintree *bt, const void *e)
Remove an element from the tree.
Definition bintree.c:342
void cstl_bintree_clear(struct cstl_bintree *bt, cstl_xtor_func_t *clr, void *priv)
Remove all elements from the tree.
Definition bintree.c:552
@ CSTL_BINTREE_VISIT_ORDER_LEAF
The only visit to an element that has no children.
Definition bintree.h:263
@ CSTL_BINTREE_VISIT_ORDER_POST
The last visit to an element, after both children have/would have been visited.
Definition bintree.h:261
@ CSTL_BINTREE_VISIT_ORDER_MID
The second visit to an element, after its first child has/would have been visited.
Definition bintree.h:256
@ CSTL_BINTREE_VISIT_ORDER_PRE
The first visit to an element that has at least one child.
Definition bintree.h:251
@ CSTL_BINTREE_FOREACH_DIR_REV
Each element in the tree is visited from right-to-left.
Definition bintree.h:279
@ CSTL_BINTREE_FOREACH_DIR_FWD
Each element in the tree is visited from left-to-right.
Definition bintree.h:277
Node to anchor an element within a binary tree.
Definition bintree.h:49
Binary tree object.
Definition bintree.h:63