blob: e32d8a5dac42e0ce3fd8eb8f57417ac1d8e95769 [file] [log] [blame]
/**
* @addtogroup hashtable
* @{
*/
/**
* @file rbt_tree.h
* @brief Red-Black Tree
*/
/*
* Implementation of RedBlack trees
* Macros and algorithms
*/
/*
* This implementation of RedBlack trees was copied from
* the STL library and adapted to a C environment.
*/
/*
* RB tree implementation -*- C++ -*-
* Copyright (C) 2001 Free Software Foundation, Inc.
*
* This file is part of the GNU ISO C++ Library. This library is free
* software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option)
* any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this library; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
/*
*
* Copyright (c) 1996,1997
* Silicon Graphics Computer Systems, Inc.
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Silicon Graphics makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*
* Copyright (c) 1994
* Hewlett-Packard Company
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Hewlett-Packard Company makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*
*/
/* NOTE: This is an internal header file, included by other STL headers.
* You should not attempt to use it directly.
*/
/*
Red-black tree class, designed for use in implementing STL
associative containers (set, multiset, map, and multimap). The
insertion and deletion algorithms are based on those in Cormen,
Leiserson, and Rivest, Introduction to Algorithms (MIT Press, 1990),
except that
(1) the header cell is maintained with links not only to the root
but also to the leftmost node of the tree, to enable constant time
begin(), and to the rightmost node of the tree, to enable linear time
performance when used with the generic set algorithms (set_union,
etc.);
(2) when a node being deleted has two children its successor node is
relinked into its place, rather than copied, so that the only
iterators invalidated are those referring to the deleted node.
*/
#ifndef RBT_TREE_H
#define RBT_TREE_H
/*
* For RBT_HEAD_INIT, RBT_COUNT, RBT_RIGHTMOST and RBT_LEFTMOST :
* __header is the header
*/
#define RBT_HEAD_INIT(__header) \
((__header)->root = 0, \
(__header)->leftmost = 0, \
(__header)->rightmost = 0, \
(__header)->rbt_num_node = 0)
#define RBT_COUNT(__header) ((__header)->rbt_num_node)
#define RBT_RIGHTMOST(__header) ((__header)->rightmost)
#define RBT_LEFTMOST(__header) ((__header)->leftmost)
/*
* For RBT_VALUE :
* __node is any node
*/
#define RBT_VALUE(__node) ((__node)->rbt_value)
/*
* For RBT_OPAQ :
* __node is any node
*/
#define RBT_OPAQ(__node) ((__node)->rbt_opaq)
/*
* For RBT_INCREMENT and RBT_DECREMENT :
* __node is the starting node
* __x is a temporary variable
* __node is modified to point to the next/previous node
*/
#define RBT_INCREMENT(__node) ({ \
if ((__node)->next) { \
__node = (__node)->next; \
while ((__node)->left) \
(__node) = (__node)->left; \
} else { \
struct rbt_node *__x; \
do { \
__x = (__node); \
} while ((((__node) = (__node)->parent)) && \
((__node)->next == __x)); \
} \
})
#define RBT_DECREMENT(__node) ({ \
if ((__node)->left) { \
__node = (__node)->left; \
while ((__node)->next) \
(__node) = (__node)->next; \
} else { \
struct rbt_node *__x; \
do { \
__x = (__node); \
} while ((((__node) = (__node)->parent)) && \
((__node)->left == __x)); \
} \
})
/*
* For RBT_LOOP and RBT_LOOP_REVERSE :
* __header is the header
* __it is the iterator (type rbt_node *)
*
* These macros must be used with, respectively,
* RBT_INCREMENT and RBT_DECREMENT.
*/
#define RBT_LOOP(__header, __it) \
for ((__it) = (__header)->leftmost; (__it);)
#define RBT_LOOP_REVERSE(__header, __it) \
for ((__it) = (__header)->rightmost; (__it);)
/*
* For RBT_ROTATE_LEFT and RBT_ROTATE_RIGHT :
* __xx is pointer to the pivotal node
* __yy is a temporary variable
* the pivotal node is not modified except its links in the tree
* For RBT_ROTATE_LEFT, (__xx)->next must not be zero.
* For RBT_ROTATE_RIGHT, (__xx)->left must not be zero.
*/
#define RBT_ROTATE_LEFT(__xx) ({ \
struct rbt_node *__yy; \
__yy = (__xx)->next; \
(__xx)->next = __yy->left; \
if (((__xx)->next)) { \
__yy->left->parent = (__xx); \
__yy->left->anchor = &(__xx)->next; \
} \
__yy->parent = (__xx)->parent; \
__yy->left = (__xx); \
__yy->anchor = (__xx)->anchor; \
(__xx)->parent = __yy; \
(__xx)->anchor = &__yy->left; \
*__yy->anchor = __yy; \
})
#define RBT_ROTATE_RIGHT(__xx) ({ \
struct rbt_node *__yy; \
__yy = (__xx)->left; \
(__xx)->left = __yy->next; \
if ((__xx)->left) { \
__yy->next->parent = (__xx); \
__yy->next->anchor = &(__xx)->left; \
} \
__yy->parent = (__xx)->parent; \
__yy->next = (__xx); \
__yy->anchor = (__xx)->anchor; \
(__xx)->parent = __yy; \
(__xx)->anchor = &__yy->next; \
*__yy->anchor = __yy; \
})
/*
* For RBT_INSERT :
* __node is the new node to be inserted
* __par is the node which will be the first parent of __node
* __node and __par are not modified
* *__node and *__par are modified
* __header is the header node
* __x and __y are temporary variables
*
* __par must have been returned by RBT_FIND (successful or not).
* If RBT_FIND was not successful, __par cannot have two children :
* - If __node->rbt_value > __par->rbt_value, then __par->next is NULL.
* __node will be installed at __par->next.
* - If __node->rbt_value < __par->rbt_value, then __par->left is NULL.
* __node will be installed at __par->next.
* If RBT_FIND was successful :
* - If __par has two children, search the previous node and replace
* __par by this previous node. Then insert __node at __par->next.
* - If __par->left is free, install __node at __par->left.
* - Otherwise, install __node at __par->next.
*
* If this insertion unbalances the tree, __node may end in a different
* position.
*/
#define RBT_INSERT(__header, __node, __par) ({ \
struct rbt_node *__x, *__y; \
(__header)->rbt_num_node++; \
__y = (__par); \
if (__y == 0) { \
(__node)->anchor = &(__header)->root; \
(__header)->root = (__node); \
(__header)->rightmost = (__node); \
(__header)->leftmost = (__node); \
} else if (((__node)->rbt_value == __y->rbt_value) && \
__y->next && __y->left) { \
__y = __y->left; \
while (__y->next) \
__y = __y->next; \
__y->next = (__node); \
(__node)->anchor = &__y->next; \
} else if (((__node)->rbt_value > __y->rbt_value) || \
(((__node)->rbt_value == __y->rbt_value) \
&& __y->left)) { \
__y->next = (__node); \
(__node)->anchor = &__y->next; \
if (__y == (__header)->rightmost) { \
(__header)->rightmost = (__node); \
} \
} else { \
__y->left = (__node); \
(__node)->anchor = &__y->left; \
if (__y == (__header)->leftmost) { \
(__header)->leftmost = (__node); \
} \
} \
(__node)->rbt_flags = 0; \
(__node)->parent = __y; \
(__node)->left = 0; \
(__node)->next = 0; \
__x = (__node); \
while (__x->parent) { \
__x->rbt_flags |= RBT_RED; \
if ((__x->parent->rbt_flags & RBT_RED) == 0) \
break; \
if (__x->parent == __x->parent->parent->left) { \
__y = __x->parent->parent->next; \
if ((__y == 0) || ((__y->rbt_flags & RBT_RED) \
== 0)) { \
if (__x == __x->parent->next) { \
__x = __x->parent; \
RBT_ROTATE_LEFT(__x); \
} \
__x->parent->rbt_flags &= ~RBT_RED; \
__x = __x->parent->parent; \
__x->rbt_flags |= RBT_RED; \
RBT_ROTATE_RIGHT(__x); \
break; \
} \
} else { \
__y = __x->parent->parent->left; \
if ((__y == 0) || ((__y->rbt_flags & RBT_RED) \
== 0)) { \
if (__x == __x->parent->left) { \
__x = __x->parent; \
RBT_ROTATE_RIGHT(__x); \
} \
__x->parent->rbt_flags &= ~RBT_RED; \
__x = __x->parent->parent; \
__x->rbt_flags |= RBT_RED; \
RBT_ROTATE_LEFT(__x); \
break; \
} \
} \
__x->parent->rbt_flags &= ~RBT_RED; \
__y->rbt_flags &= ~RBT_RED; \
__x = __x->parent->parent; \
} \
})
/*
* For RBT_UNLINK :
* __node is the node to unlink
* __header is the header node
* __x, __z and __y are temporary variables
* __node->rbt_flags may be modified
* otherwise, __node is not modified
*/
#define RBT_UNLINK(__header, __node) ({ \
struct rbt_node *__x, *__y, *__z; \
(__header)->rbt_num_node--; \
if ((__node)->left && (__node)->next) { \
__y = (__node)->next; \
while (__y->left) \
__y = __y->left; \
if (((__node)->rbt_flags & RBT_RED) != \
(__y->rbt_flags & RBT_RED)) { \
(__node)->rbt_flags ^= RBT_RED; \
__y->rbt_flags ^= RBT_RED; \
} \
__x = __y->next; \
(__node)->left->parent = __y; \
(__node)->left->anchor = &__y->left; \
__y->left = (__node)->left; \
if (__y == (__node)->next) { \
__z = __y; \
} else { \
__z = __y->parent; \
if (__x) { \
__x->parent = __z; \
__x->anchor = &__z->left; \
} \
__z->left = __x; /* __y was a child of left */ \
__y->next = (__node)->next; \
(__node)->next->parent = __y; \
(__node)->next->anchor = &__y->next; \
} \
__y->parent = (__node)->parent; \
__y->anchor = (__node)->anchor; \
*(__node)->anchor = __y; \
} else { \
__z = (__node)->parent; \
__x = (__node)->next; /* __x might be NULL */ \
if (__x == 0) \
__x = (__node)->left; \
if (__x) { \
__x->parent = __z; \
__x->anchor = (__node)->anchor; \
} \
if ((__header)->leftmost == (__node)) { \
if (__x) { \
__y = __x; \
while (__y->left) \
__y = __y->left; \
(__header)->leftmost = __y; \
} else { \
(__header)->leftmost = __z; \
} \
} \
if ((__header)->rightmost == (__node)) { \
if (__x) { \
__y = __x; \
while (__y->next) \
__y = __y->next; \
(__header)->rightmost = __y; \
} else { \
(__header)->rightmost = __z; \
} \
} \
*(__node)->anchor = __x; \
} \
if (!((__node)->rbt_flags & RBT_RED)) { \
while ((__z) && \
((__x == 0) || !(__x->rbt_flags & RBT_RED))) { \
if (__x == __z->left) { \
__y = __z->next; \
if (__y->rbt_flags & RBT_RED) { \
__y->rbt_flags &= ~RBT_RED; \
__z->rbt_flags |= RBT_RED; \
RBT_ROTATE_LEFT(__z); \
__y = __z->next; \
} \
if ((__y->left == 0 || \
!(__y->left->rbt_flags & RBT_RED)) \
&& (__y->next == 0 || \
!(__y->next->rbt_flags & \
RBT_RED))) { \
__y->rbt_flags |= RBT_RED; \
__x = __z; \
__z = __z->parent; \
} else { \
if (__y->next == 0 || \
!(__y->next->rbt_flags & \
RBT_RED)) { \
if (__y->left) \
__y->left->rbt_flags \
&= ~RBT_RED; \
__y->rbt_flags |= RBT_RED; \
RBT_ROTATE_RIGHT(__y); \
__y = __z->next; \
} \
__y->rbt_flags &= ~RBT_RED; \
__y->rbt_flags |= \
__z->rbt_flags & RBT_RED; \
__z->rbt_flags &= ~RBT_RED; \
if (__y->next) \
__y->next->rbt_flags \
&= ~RBT_RED; \
RBT_ROTATE_LEFT(__z); \
break; \
} \
} else { \
__y = __z->left; \
if (__y->rbt_flags & RBT_RED) { \
__y->rbt_flags &= ~RBT_RED; \
__z->rbt_flags |= RBT_RED; \
RBT_ROTATE_RIGHT(__z); \
__y = __z->left; \
} \
if ((__y->left == 0 || \
!(__y->left->rbt_flags & RBT_RED)) \
&& (__y->next == 0 || \
!(__y->next->rbt_flags & \
RBT_RED))) { \
__y->rbt_flags |= RBT_RED; \
__x = __z; \
__z = __z->parent; \
} else { \
if (__y->left == 0 || \
!(__y->left->rbt_flags & \
RBT_RED)) { \
if (__y->next) \
__y->next->rbt_flags \
&= ~RBT_RED; \
__y->rbt_flags |= RBT_RED; \
RBT_ROTATE_LEFT(__y); \
__y = __z->left; \
} \
__y->rbt_flags &= ~RBT_RED; \
__y->rbt_flags |= __z->rbt_flags\
& RBT_RED; \
__z->rbt_flags &= ~RBT_RED; \
if (__y->left) \
__y->left->rbt_flags \
&= ~RBT_RED; \
RBT_ROTATE_RIGHT(__z); \
break; \
} \
} \
} \
if (__x) \
__x->rbt_flags &= ~RBT_RED; \
} \
})
/*
* For RBT_FIND
* __header is the header node
* __node will contain the found node
* __val is a uint64_t and contains the value to search
* __x is a temporary variable
* No nodes are modified
* __node is modified
*
* When RBT_FIND returns, __node points to the node whose value is __val.
* If multiple nodes have the value __val, only one is returned.
* If no node has the value __val, __node points to the preceeding
* or the following node and __node cannot have two children.
* After the call, if __node is NULL, the tree is empty.
* To check for success :
* if (((__node) != 0) && (RBT_VALUE(__node) == (__val))) {
* -- node found --
* ...
* }
*
* RBT_FIND must be called before inserting a node using RBT_INSERT.
*/
#define RBT_FIND(__header, __node, __val) ({ \
struct rbt_node *__x; \
(__node) = (__header)->root; \
__x = (__header)->root; \
while (__x) { \
(__node) = __x; \
if (__x->rbt_value > (__val)) { \
__x = __x->left; \
} else if (__x->rbt_value < (__val)) { \
__x = __x->next; \
} else { \
break; \
} \
} \
})
/*
* For RBT_FIND_LEFT
* __header is the header node
* __node will contain the found node
* __val is a uint64_t and contains the value to search
* __x is a temporary variable
* No nodes are modified
* __node is modified
*
* When RBT_FIND_LEFT returns, __node points to the leftmost node
* whose value is __val.
* If multiple nodes have the value __val, only one is returned.
* If no node has the value __val, __node is NULL.
* This is different from RBT_FIND. RBT_FIND_LEFT cannot be used
* to insert a new node.
* To check for success :
* if ((__node) != 0) {
* -- node found --
* ...
* }
*/
#define RBT_FIND_LEFT(__header, __node, __val) ({ \
struct rbt_node *__x; \
(__node) = 0; \
__x = (__header)->root; \
while (__x) { \
if (__x->rbt_value > (__val)) { \
__x = __x->left; \
} else if (__x->rbt_value < (__val)) { \
__x = __x->next; \
} else { \
(__node) = __x; \
while (__x) { \
while ((__x = __x->left)) { \
if (__x->rbt_value < (__val)) \
break; \
(__node) = __x; \
} \
if (__x == 0) \
break; \
while ((__x = __x->next)) { \
if (__x->rbt_value == \
(__val)) { \
(__node) = __x; \
break; \
} \
} \
} \
break; \
} \
} \
})
/*
* RBT_BLACK_COUNT counts the number of black nodes in the parents of a node
*/
#define RBT_BLACK_COUNT(__node, __sum) ({ \
for ((__sum) = 0; (__node); (__node) = (__node)->parent) { \
if (!((__node)->rbt_flags & RBT_RED)) \
++(__sum); \
} \
})
#define RBT_VERIFY(__header, __it, __error) ({ \
int __len, __num, __sum; \
struct rbt_node *__L, *__R; \
(__error) = 0; \
if ((__header)->rbt_num_node == 0) { \
if (((__header)->leftmost) || \
((__header)->rightmost) || \
((__header)->root)) { \
(__error) = 1; \
(__it) = 0; \
} \
} else { \
__L = (__header)->leftmost; \
RBT_BLACK_COUNT(__L, __len) \
__num = 0; \
RBT_LOOP((__header), (__it)) { \
if ((__it)->parent == 0) { \
if (((__it) != (__header)->root) || \
((__it)->anchor != \
&(__header)->root)) { \
(__error) = 2; \
break; \
} \
} else { \
if ((((__it) == (__it)->parent->next) && \
((__it)->anchor != \
&(__it)->parent->next)) || \
(((__it) == (__it)->parent->left) && \
((__it)->anchor != \
&(__it)->parent->left))) { \
(__error) = 2; \
break; \
} \
} \
__L = (__it)->left; \
__R = (__it)->next; \
if (((__it)->rbt_flags & RBT_RED) && \
((__L && (__L->rbt_flags & RBT_RED)) || \
(__R && (__R->rbt_flags & RBT_RED)))) { \
(__error) = 3; \
break; \
} \
if (__L && (__L->rbt_value > (__it)->rbt_value)) { \
(__error) = 4; \
break; \
} \
if (__R && (__R->rbt_value < (__it)->rbt_value)) { \
(__error) = 5; \
break; \
} \
if (!__L && !__R) { \
__L = (__it); \
RBT_BLACK_COUNT(__L, __sum) \
if (__sum != __len) { \
(__error) = 6; \
break; \
} \
} \
__num++; \
RBT_INCREMENT(__it) \
} \
if (((__error) == 0) && (__num != \
(__header)->rbt_num_node)) { \
(__error) = 7; \
(__it) = 0; \
} \
/* test RBT_DECREMENT */ \
__num = 0; \
RBT_LOOP_REVERSE(__header, __it) { \
__num++; \
RBT_DECREMENT(__it) \
} \
if (((__error) == 0) && (__num != \
(__header)->rbt_num_node)) { \
(__error) = 8; \
(__it) = 0; \
} \
if ((__error) == 0) { \
__L = (__header)->root; \
while ((__L)->left) \
(__L) = (__L)->left; \
__R = (__header)->root; \
while ((__R)->next) \
(__R) = (__R)->next; \
if ((__L != (__header)->leftmost) || \
(__R != (__header)->rightmost)) { \
(__error) = 9; \
(__it) = 0; \
} \
} \
if (((__error) == 0) && ((__header)->root) && \
!((__header)->root->parent == 0)) { \
(__error) = 10; \
(__it) = 0; \
} \
} \
})
#endif /* RBT_TREE_H */
/** @{ */