source: rtems/cpukit/score/include/rtems/score/rbtree.h @ 993f5ac

4.115
Last change on this file since 993f5ac was 993f5ac, checked in by Sebastian Huber <sebastian.huber@…>, on 07/23/14 at 11:03:54

rbtree: Simplify insert and extract

Simplify _RBTree_Insert() and _RBTree_Extract(). Remove more
superfluous NULL pointer checks. Change _RBTree_Is_root() to use only
the node. Add parent parameter to _RBTree_Sibling(). Delete
_RBTree_Grandparent() and _RBTree_Parent_sibling().

  • Property mode set to 100644
File size: 14.6 KB
RevLine 
[bd9baa81]1/**
2 *  @file  rtems/score/rbtree.h
3 *
[319cb20]4 *  @brief Constants and Structures Associated with the Red-Black Tree Handler
5 *
[bd9baa81]6 *  This include file contains all the constants and structures associated
7 *  with the Red-Black Tree Handler.
8 */
9
10/*
11 *  Copyright (c) 2010 Gedare Bloom.
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
[c499856]15 *  http://www.rtems.org/license/LICENSE.
[bd9baa81]16 */
17
18#ifndef _RTEMS_SCORE_RBTREE_H
19#define _RTEMS_SCORE_RBTREE_H
20
[050adc2]21#include <stddef.h>
22
[93fb3cb0]23#include <rtems/score/address.h>
24
25#ifdef __cplusplus
26extern "C" {
27#endif
28
[bd9baa81]29/**
30 *  @defgroup ScoreRBTree Red-Black Tree Handler
31 *
[d8cd045c]32 *  @ingroup Score
33 *
[bd9baa81]34 *  The Red-Black Tree Handler is used to manage sets of entities.  This handler
35 *  provides two data structures.  The rbtree Node data structure is included
36 *  as the first part of every data structure that will be placed on
37 *  a RBTree.  The second data structure is rbtree Control which is used
38 *  to manage a set of rbtree Nodes.
39 */
40/**@{*/
41
[4b72da4]42/**
43 *  @typedef RBTree_Node
44 *
45 *  This type definition promotes the name for the RBTree Node used by
46 *  all RTEMS code.  It is a separate type definition because a forward
47 *  reference is required to define it.  See @ref RBTree_Node_struct for
48 *  detailed information.
49 */
50typedef struct RBTree_Node_struct RBTree_Node;
[bd9baa81]51
[4b72da4]52/**
53 * This enum type defines the colors available for the RBTree Nodes
54 */
55typedef enum {
56  RBT_BLACK,
57  RBT_RED
58} RBTree_Color;
[bd9baa81]59
[4b72da4]60/**
61 *  @struct RBTree_Node_struct
62 *
63 *  This is used to manage each element (node) which is placed
64 *  on a RBT.
65 *
66 *  @note Typically, a more complicated structure will use the
67 *        rbtree package.  The more complicated structure will
68 *        include a rbtree node as the first element in its
69 *        control structure.  It will then call the rbtree package
70 *        with a pointer to that node element.  The node pointer
71 *        and the higher level structure start at the same address
72 *        so the user can cast the pointers back and forth.
73 *
74 */
75struct RBTree_Node_struct {
76  /** This points to the node's parent */
77  RBTree_Node *parent;
78  /** child[0] points to the left child, child[1] points to the right child */
79  RBTree_Node *child[2];
80  /** The color of the node. Either red or black */
81  RBTree_Color color;
82};
[dacdda30]83
[4b72da4]84/**
85 *  This type indicates the direction.
86 */
87typedef enum {
88  RBT_LEFT=0,
89  RBT_RIGHT=1
90} RBTree_Direction;
[bd9baa81]91
[60fe374]92/**
93 * @brief Integer type for compare results.
94 *
95 * The type is large enough to represent pointers and 32-bit signed integers.
96 *
97 * @see RBTree_Compare.
98 */
99typedef long RBTree_Compare_result;
100
[74f1c73e]101/**
[64939bc]102 * @brief Compares two red-black tree nodes.
103 *
104 * @param[in] first The first node.
105 * @param[in] second The second node.
106 *
107 * @retval positive The key value of the first node is greater than the one of
108 *   the second node.
109 * @retval 0 The key value of the first node is equal to the one of the second
110 *   node.
111 * @retval negative The key value of the first node is less than the one of the
112 *   second node.
[74f1c73e]113 */
[60fe374]114typedef RBTree_Compare_result ( *RBTree_Compare )(
[64939bc]115  const RBTree_Node *first,
116  const RBTree_Node *second
[74f1c73e]117);
118
[4b72da4]119/**
120 *  @struct RBTree_Control
121 *
122 * This is used to manage a RBT.  A rbtree consists of a tree of zero or more
123 * nodes.
124 *
125 * @note This implementation does not require special checks for
126 *   manipulating the root element of the RBT.
127 *   To accomplish this the @a RBTree_Control structure can be overlaid
128 *   with a @ref RBTree_Node structure to act as a "dummy root",
129 *   which has a NULL parent and its left child is the root.
130 */
[bd9baa81]131
[4b72da4]132/* the RBTree_Control is actually part of the RBTree structure as an
133 * RBTree_Node. The mapping of fields from RBTree_Control to RBTree_Node are:
134 *   permanent_null == parent
135 *   root == left
136 *   first[0] == right
137 */
138typedef struct {
139  /** This points to a NULL. Useful for finding the root. */
140  RBTree_Node *permanent_null;
141  /** This points to the root node of the RBT. */
142  RBTree_Node *root;
143  /** This points to the min and max nodes of this RBT. */
144  RBTree_Node *first[2];
145} RBTree_Control;
[bd9baa81]146
[4b72da4]147/**
148 *  @brief RBTree initializer for an empty rbtree with designator @a name.
149 */
[64939bc]150#define RBTREE_INITIALIZER_EMPTY( name ) \
151  { NULL, NULL, { NULL, NULL } }
[bd9baa81]152
[4b72da4]153/**
154 *  @brief RBTree definition for an empty rbtree with designator @a name.
155 */
[64939bc]156#define RBTREE_DEFINE_EMPTY( name ) \
157  RBTree_Control name = RBTREE_INITIALIZER_EMPTY( name )
[bd9baa81]158
[4b72da4]159/**
160 *  @brief RBTree_Node initializer for an empty node with designator @a name.
161 */
[64939bc]162#define RBTREE_NODE_INITIALIZER_EMPTY( name ) \
163  { NULL, { NULL, NULL }, RBT_RED }
[bd9baa81]164
[4b72da4]165/**
166 *  @brief RBTree definition for an empty rbtree with designator @a name.
167 */
[64939bc]168#define RBTREE_NODE_DEFINE_EMPTY( name ) \
169  RBTree_Node name = RBTREE_NODE_INITIALIZER_EMPTY( name )
[bd9baa81]170
[4b72da4]171/**
[319cb20]172 *  @brief Initialize a RBTree Header.
[4b72da4]173 *
174 *  This routine initializes @a the_rbtree structure to manage the
175 *  contiguous array of @a number_nodes nodes which starts at
176 *  @a starting_address.  Each node is of @a node_size bytes.
[319cb20]177 *
[f2f63d1]178 *  @param[in] the_rbtree is the pointer to rbtree header
[64939bc]179 *  @param[in] compare The node compare function.
[f2f63d1]180 *  @param[in] starting_address is the starting address of first node
181 *  @param[in] number_nodes is the number of nodes in rbtree
182 *  @param[in] node_size is the size of node in bytes
[64939bc]183 *  @param[in] is_unique If true, then reject nodes with a duplicate key, else
184 *    otherwise.
[4b72da4]185 */
186void _RBTree_Initialize(
[64939bc]187  RBTree_Control *the_rbtree,
188  RBTree_Compare  compare,
189  void           *starting_address,
190  size_t          number_nodes,
191  size_t          node_size,
192  bool            is_unique
[4b72da4]193);
[bd9baa81]194
[4b72da4]195/**
[833dd90]196 * @brief Tries to find a node for the specified key in the tree.
[4b72da4]197 *
[833dd90]198 * @param[in] the_rbtree The red-black tree control.
199 * @param[in] the_node A node specifying the key.
[64939bc]200 * @param[in] compare The node compare function.
201 * @param[in] is_unique If true, then return the first node with a key equal to
202 *   the one of the node specified if it exits, else return the last node if it
203 *   exists.
[4b72da4]204 *
[833dd90]205 * @retval node A node corresponding to the key.  If the tree is not unique
206 * and contains duplicate keys, the set of duplicate keys acts as FIFO.
207 * @retval NULL No node exists in the tree for the key.
[53afcfd2]208 */
[4ea97d24]209RBTree_Node *_RBTree_Find(
[0ca61727]210  const RBTree_Control *the_rbtree,
[64939bc]211  const RBTree_Node    *the_node,
212  RBTree_Compare        compare,
213  bool                  is_unique
[53afcfd2]214);
215
[4b72da4]216/**
[639117f]217 * @brief Inserts the node into the red-black tree.
[4b72da4]218 *
[639117f]219 * In case the node is already a node of a tree, then this function yields
220 * unpredictable results.
[4b72da4]221 *
[64939bc]222 * @param[in] the_rbtree The red-black tree control.
223 * @param[in] the_node The node to insert.
224 * @param[in] compare The node compare function.
225 * @param[in] is_unique If true, then reject nodes with a duplicate key, else
[639117f]226 *   insert nodes in FIFO order in case the key value is equal to existing nodes.
[64939bc]227 *
[d7a94693]228 * @retval NULL Successfully inserted.
229 * @retval existing_node This is a unique insert and there exists a node with
230 *   an equal key in the tree already.
[4b72da4]231 */
[4ea97d24]232RBTree_Node *_RBTree_Insert(
[4b72da4]233  RBTree_Control *the_rbtree,
[64939bc]234  RBTree_Node    *the_node,
235  RBTree_Compare  compare,
236  bool            is_unique
[4b72da4]237);
[bd9baa81]238
[4b72da4]239/**
[8abbbdde]240 * @brief Extracts (removes) the node from the red-black tree.
[4b72da4]241 *
[8abbbdde]242 * This function does not set the node off-tree.  In case this is desired, then
[6e93c836]243 * call _RBTree_Set_off_tree() after the extraction.
[8abbbdde]244 *
245 * In case the node to extract is not a node of the tree, then this function
246 * yields unpredictable results.
247 *
248 * @param[in] the_rbtree The red-black tree control.
249 * @param[in] the_node The node to extract.
[4b72da4]250 */
[4ea97d24]251void _RBTree_Extract(
[4b72da4]252  RBTree_Control *the_rbtree,
253  RBTree_Node *the_node
254);
[bd9baa81]255
[dc62a48c]256/**
257 * @brief Returns the in-order next node of a node.
258 *
259 * @param[in] node The node.
260 * @param[in] dir The direction.
261 *
262 * @retval NULL The in-order next node does not exist.
263 * @retval otherwise The next node.
264 */
[4ea97d24]265RBTree_Node *_RBTree_Next(
[dc62a48c]266  const RBTree_Node *node,
267  RBTree_Direction dir
268);
269
[112396de]270/**
[6e93c836]271 * @brief Sets a red-black tree node as off-tree.
[112396de]272 *
[6e93c836]273 * Do not use this function on nodes which are a part of a tree.
[112396de]274 *
[6e93c836]275 * @param[in] the_node The node to set off-tree.
276 *
277 * @see _RBTree_Is_node_off_tree().
[93fb3cb0]278 */
[6e93c836]279RTEMS_INLINE_ROUTINE void _RBTree_Set_off_tree( RBTree_Node *the_node )
[93fb3cb0]280{
[6e93c836]281  the_node->parent = NULL;
[93fb3cb0]282}
283
284/**
[6e93c836]285 * @brief Returns true, if this red-black tree node is off-tree, and false
286 * otherwise.
287 *
288 * @param[in] the_node The node to test.
[112396de]289 *
[6e93c836]290 * @retval true The node is not a part of a tree (off-tree).
291 * @retval false Otherwise.
292 *
293 * @see _RBTree_Set_off_tree().
[112396de]294 */
[6e93c836]295RTEMS_INLINE_ROUTINE bool _RBTree_Is_node_off_tree(
296  const RBTree_Node *the_node
297)
[93fb3cb0]298{
[6e93c836]299  return the_node->parent == NULL;
[93fb3cb0]300}
[112396de]301
[93fb3cb0]302/**
[993f5ac]303 * @brief Returns a pointer to root node of the red-black tree.
[93fb3cb0]304 *
[993f5ac]305 * The root node may change after insert or extract operations.
306 *
307 * @param[in] the_rbtree The red-black tree control.
308 *
309 * @retval NULL The tree is empty.
310 * @retval root The root node.
311 *
312 * @see _RBTree_Is_root().
[93fb3cb0]313 */
314RTEMS_INLINE_ROUTINE RBTree_Node *_RBTree_Root(
315  const RBTree_Control *the_rbtree
316)
317{
318  return the_rbtree->root;
319}
320
321/**
322 * @brief Return pointer to RBTree's first node.
323 *
324 * This function returns a pointer to the first node on @a the_rbtree,
325 * where @a dir specifies whether to return the minimum (0) or maximum (1).
326 */
327RTEMS_INLINE_ROUTINE RBTree_Node *_RBTree_First(
328  const RBTree_Control *the_rbtree,
329  RBTree_Direction dir
330)
331{
332  return the_rbtree->first[dir];
333}
334
335/**
[993f5ac]336 * @brief Returns a pointer to the parent of this node.
[93fb3cb0]337 *
[993f5ac]338 * The node must have a parent, thus it is invalid to use this function for the
339 * root node or a node that is not part of a tree.  To test for the root node
340 * compare with _RBTree_Root() or use _RBTree_Is_root().
341 *
342 * @param[in] the_node The node of interest.
343 *
344 * @retval parent The parent of this node.
345 * @retval undefined The node is the root node or not part of a tree.
[93fb3cb0]346 */
347RTEMS_INLINE_ROUTINE RBTree_Node *_RBTree_Parent(
348  const RBTree_Node *the_node
349)
350{
351  return the_node->parent;
352}
353
354/**
355 * @brief Return pointer to the left of this node.
356 *
357 * This function returns a pointer to the left node of this node.
358 *
359 * @param[in] the_node is the node to be operated upon.
360 *
361 * @return This method returns the left node on the rbtree.
362 */
363RTEMS_INLINE_ROUTINE RBTree_Node *_RBTree_Left(
364  const RBTree_Node *the_node
365)
366{
367  return the_node->child[RBT_LEFT];
368}
369
370/**
371 * @brief Return pointer to the right of this node.
372 *
373 * This function returns a pointer to the right node of this node.
374 *
375 * @param[in] the_node is the node to be operated upon.
376 *
377 * @return This method returns the right node on the rbtree.
378 */
379RTEMS_INLINE_ROUTINE RBTree_Node *_RBTree_Right(
380  const RBTree_Node *the_node
381)
382{
383  return the_node->child[RBT_RIGHT];
384}
385
386/**
387 * @brief Is the RBTree empty.
388 *
389 * This function returns true if there are no nodes on @a the_rbtree and
390 * false otherwise.
391 *
392 * @param[in] the_rbtree is the rbtree to be operated upon.
393 *
394 * @retval true There are no nodes on @a the_rbtree.
395 * @retval false There are nodes on @a the_rbtree.
396 */
397RTEMS_INLINE_ROUTINE bool _RBTree_Is_empty(
398  const RBTree_Control *the_rbtree
399)
400{
401  return (the_rbtree->root == NULL);
402}
403
404/**
405 * @brief Is this the first node on the RBTree.
406 *
407 * This function returns true if @a the_node is the first node on
408 * @a the_rbtree and false otherwise. @a dir specifies whether first means
409 * minimum (0) or maximum (1).
410 *
411 * @retval true @a the_node is the first node on @a the_rbtree.
412 * @retval false @a the_node is not the first node on @a the_rbtree.
413 *
414 */
415RTEMS_INLINE_ROUTINE bool _RBTree_Is_first(
416  const RBTree_Control *the_rbtree,
417  const RBTree_Node *the_node,
418  RBTree_Direction dir
419)
420{
421  return (the_node == _RBTree_First(the_rbtree, dir));
422}
423
424/**
[993f5ac]425 * @brief Returns true if this node is the root node of a red-black tree, and
[93fb3cb0]426 * false otherwise.
427 *
[993f5ac]428 * The root node may change after insert or extract operations.  In case the
429 * node is not a node of a tree, then this function yields unpredictable
430 * results.
431 *
432 * @param[in] the_node The node of interest.
433 *
434 * @retval true The node is the root node.
435 * @retval false Otherwise.
436 *
437 * @see _RBTree_Root().
[93fb3cb0]438 */
439RTEMS_INLINE_ROUTINE bool _RBTree_Is_root(
[993f5ac]440  const RBTree_Node *the_node
[93fb3cb0]441)
442{
[993f5ac]443  return _RBTree_Parent( _RBTree_Parent( the_node ) ) == NULL;
[93fb3cb0]444}
445
446/**
[b767683a]447 * @brief Finds the red-black tree control given a node in the tree.
[93fb3cb0]448 *
[b767683a]449 * In case the node is not a node of a tree, then this function yields
450 * unpredictable results.
451 *
452 * @param[in] the_node The node of interest.
453 *
454 * @return The red-black tree control of the node.
[93fb3cb0]455 */
[b767683a]456RTEMS_INLINE_ROUTINE RBTree_Control *_RBTree_Find_control(
457  const RBTree_Node *the_node
458)
[93fb3cb0]459{
[b767683a]460  RBTree_Node    *parent = the_node->parent;
461  RBTree_Control *rbtree;
462
463  do {
464    rbtree = (RBTree_Control *) parent;
465    parent = parent->parent;
466  } while ( parent != NULL );
467
468  return rbtree;
[93fb3cb0]469}
470
471/**
472 * @brief Initialize this RBTree as empty.
473 *
474 * This routine initializes @a the_rbtree to contain zero nodes.
475 */
476RTEMS_INLINE_ROUTINE void _RBTree_Initialize_empty(
[64939bc]477  RBTree_Control *the_rbtree
478)
[93fb3cb0]479{
480  the_rbtree->permanent_null   = NULL;
481  the_rbtree->root             = NULL;
[64939bc]482  the_rbtree->first[RBT_LEFT]  = NULL;
483  the_rbtree->first[RBT_RIGHT] = NULL;
[93fb3cb0]484}
485
486/**
487 * @brief Returns the predecessor of a node.
488 *
489 * @param[in] node is the node.
490 *
491 * @retval NULL The predecessor does not exist.  Otherwise it returns
492 *         the predecessor node.
493 */
[4ea97d24]494RTEMS_INLINE_ROUTINE RBTree_Node *_RBTree_Predecessor(
[93fb3cb0]495  const RBTree_Node *node
496)
497{
[4ea97d24]498  return _RBTree_Next( node, RBT_LEFT );
[93fb3cb0]499}
500
501/**
502 * @brief Returns the successor of a node.
503 *
504 * @param[in] node is the node.
505 *
506 * @retval NULL The successor does not exist.  Otherwise the successor node.
507 */
[4ea97d24]508RTEMS_INLINE_ROUTINE RBTree_Node *_RBTree_Successor(
[93fb3cb0]509  const RBTree_Node *node
510)
511{
[4ea97d24]512  return _RBTree_Next( node, RBT_RIGHT );
[93fb3cb0]513}
514
515/**
[639117f]516 * @brief Gets a node with an extremal key value from the red-black tree.
[93fb3cb0]517 *
[d7a94693]518 * This function extracts a node with the minimum or maximum key value from
519 * tree and returns a pointer to that node if it exists.  In case multiple
[639117f]520 * nodes with a minimum key value exist, then they are extracted in FIFO order.
521 * In case multiple nodes with a maximum key value exist, then they are
522 * extracted in LIFO order.
[93fb3cb0]523 *
[d7a94693]524 * @param[in] the_rbtree The red-black tree control.
525 * @param[in] dir Specifies whether to get a node with the minimum (RBT_LEFT)
526 *   or maximum (RBT_RIGHT) key value.
[93fb3cb0]527 *
[d7a94693]528 * @retval NULL The tree is empty.
[639117f]529 * @retval extremal_node A node with a minimal or maximal key value on the
[d7a94693]530 *   tree.
[93fb3cb0]531 */
[4ea97d24]532RTEMS_INLINE_ROUTINE RBTree_Node *_RBTree_Get(
[d7a94693]533  RBTree_Control *the_rbtree,
534  RBTree_Direction dir
535)
[93fb3cb0]536{
[d7a94693]537  RBTree_Node *the_node = the_rbtree->first[ dir ];
538
539  if ( the_node != NULL ) {
540    _RBTree_Extract( the_rbtree, the_node );
541  }
542
[93fb3cb0]543  return the_node;
544}
545
[bd9baa81]546/**@}*/
547
[93fb3cb0]548#ifdef __cplusplus
549}
550#endif
551
[bd9baa81]552#endif
[53afcfd2]553/* end of include file */
Note: See TracBrowser for help on using the repository browser.