linux-old/lib/rbtree.c
<<
>>
Prefs
   1/*
   2  Red Black Trees
   3  (C) 1999  Andrea Arcangeli <andrea@suse.de>
   4  
   5  This program is free software; you can redistribute it and/or modify
   6  it under the terms of the GNU General Public License as published by
   7  the Free Software Foundation; either version 2 of the License, or
   8  (at your option) any later version.
   9
  10  This program is distributed in the hope that it will be useful,
  11  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  GNU General Public License for more details.
  14
  15  You should have received a copy of the GNU General Public License
  16  along with this program; if not, write to the Free Software
  17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18
  19  linux/lib/rbtree.c
  20*/
  21
  22#include <linux/rbtree.h>
  23#include <linux/module.h>
  24
  25static void __rb_rotate_left(rb_node_t * node, rb_root_t * root)
  26{
  27        rb_node_t * right = node->rb_right;
  28
  29        if ((node->rb_right = right->rb_left))
  30                right->rb_left->rb_parent = node;
  31        right->rb_left = node;
  32
  33        if ((right->rb_parent = node->rb_parent))
  34        {
  35                if (node == node->rb_parent->rb_left)
  36                        node->rb_parent->rb_left = right;
  37                else
  38                        node->rb_parent->rb_right = right;
  39        }
  40        else
  41                root->rb_node = right;
  42        node->rb_parent = right;
  43}
  44
  45static void __rb_rotate_right(rb_node_t * node, rb_root_t * root)
  46{
  47        rb_node_t * left = node->rb_left;
  48
  49        if ((node->rb_left = left->rb_right))
  50                left->rb_right->rb_parent = node;
  51        left->rb_right = node;
  52
  53        if ((left->rb_parent = node->rb_parent))
  54        {
  55                if (node == node->rb_parent->rb_right)
  56                        node->rb_parent->rb_right = left;
  57                else
  58                        node->rb_parent->rb_left = left;
  59        }
  60        else
  61                root->rb_node = left;
  62        node->rb_parent = left;
  63}
  64
  65void rb_insert_color(rb_node_t * node, rb_root_t * root)
  66{
  67        rb_node_t * parent, * gparent;
  68
  69        while ((parent = node->rb_parent) && parent->rb_color == RB_RED)
  70        {
  71                gparent = parent->rb_parent;
  72
  73                if (parent == gparent->rb_left)
  74                {
  75                        {
  76                                register rb_node_t * uncle = gparent->rb_right;
  77                                if (uncle && uncle->rb_color == RB_RED)
  78                                {
  79                                        uncle->rb_color = RB_BLACK;
  80                                        parent->rb_color = RB_BLACK;
  81                                        gparent->rb_color = RB_RED;
  82                                        node = gparent;
  83                                        continue;
  84                                }
  85                        }
  86
  87                        if (parent->rb_right == node)
  88                        {
  89                                register rb_node_t * tmp;
  90                                __rb_rotate_left(parent, root);
  91                                tmp = parent;
  92                                parent = node;
  93                                node = tmp;
  94                        }
  95
  96                        parent->rb_color = RB_BLACK;
  97                        gparent->rb_color = RB_RED;
  98                        __rb_rotate_right(gparent, root);
  99                } else {
 100                        {
 101                                register rb_node_t * uncle = gparent->rb_left;
 102                                if (uncle && uncle->rb_color == RB_RED)
 103                                {
 104                                        uncle->rb_color = RB_BLACK;
 105                                        parent->rb_color = RB_BLACK;
 106                                        gparent->rb_color = RB_RED;
 107                                        node = gparent;
 108                                        continue;
 109                                }
 110                        }
 111
 112                        if (parent->rb_left == node)
 113                        {
 114                                register rb_node_t * tmp;
 115                                __rb_rotate_right(parent, root);
 116                                tmp = parent;
 117                                parent = node;
 118                                node = tmp;
 119                        }
 120
 121                        parent->rb_color = RB_BLACK;
 122                        gparent->rb_color = RB_RED;
 123                        __rb_rotate_left(gparent, root);
 124                }
 125        }
 126
 127        root->rb_node->rb_color = RB_BLACK;
 128}
 129EXPORT_SYMBOL(rb_insert_color);
 130
 131static void __rb_erase_color(rb_node_t * node, rb_node_t * parent,
 132                             rb_root_t * root)
 133{
 134        rb_node_t * other;
 135
 136        while ((!node || node->rb_color == RB_BLACK) && node != root->rb_node)
 137        {
 138                if (parent->rb_left == node)
 139                {
 140                        other = parent->rb_right;
 141                        if (other->rb_color == RB_RED)
 142                        {
 143                                other->rb_color = RB_BLACK;
 144                                parent->rb_color = RB_RED;
 145                                __rb_rotate_left(parent, root);
 146                                other = parent->rb_right;
 147                        }
 148                        if ((!other->rb_left ||
 149                             other->rb_left->rb_color == RB_BLACK)
 150                            && (!other->rb_right ||
 151                                other->rb_right->rb_color == RB_BLACK))
 152                        {
 153                                other->rb_color = RB_RED;
 154                                node = parent;
 155                                parent = node->rb_parent;
 156                        }
 157                        else
 158                        {
 159                                if (!other->rb_right ||
 160                                    other->rb_right->rb_color == RB_BLACK)
 161                                {
 162                                        register rb_node_t * o_left;
 163                                        if ((o_left = other->rb_left))
 164                                                o_left->rb_color = RB_BLACK;
 165                                        other->rb_color = RB_RED;
 166                                        __rb_rotate_right(other, root);
 167                                        other = parent->rb_right;
 168                                }
 169                                other->rb_color = parent->rb_color;
 170                                parent->rb_color = RB_BLACK;
 171                                if (other->rb_right)
 172                                        other->rb_right->rb_color = RB_BLACK;
 173                                __rb_rotate_left(parent, root);
 174                                node = root->rb_node;
 175                                break;
 176                        }
 177                }
 178                else
 179                {
 180                        other = parent->rb_left;
 181                        if (other->rb_color == RB_RED)
 182                        {
 183                                other->rb_color = RB_BLACK;
 184                                parent->rb_color = RB_RED;
 185                                __rb_rotate_right(parent, root);
 186                                other = parent->rb_left;
 187                        }
 188                        if ((!other->rb_left ||
 189                             other->rb_left->rb_color == RB_BLACK)
 190                            && (!other->rb_right ||
 191                                other->rb_right->rb_color == RB_BLACK))
 192                        {
 193                                other->rb_color = RB_RED;
 194                                node = parent;
 195                                parent = node->rb_parent;
 196                        }
 197                        else
 198                        {
 199                                if (!other->rb_left ||
 200                                    other->rb_left->rb_color == RB_BLACK)
 201                                {
 202                                        register rb_node_t * o_right;
 203                                        if ((o_right = other->rb_right))
 204                                                o_right->rb_color = RB_BLACK;
 205                                        other->rb_color = RB_RED;
 206                                        __rb_rotate_left(other, root);
 207                                        other = parent->rb_left;
 208                                }
 209                                other->rb_color = parent->rb_color;
 210                                parent->rb_color = RB_BLACK;
 211                                if (other->rb_left)
 212                                        other->rb_left->rb_color = RB_BLACK;
 213                                __rb_rotate_right(parent, root);
 214                                node = root->rb_node;
 215                                break;
 216                        }
 217                }
 218        }
 219        if (node)
 220                node->rb_color = RB_BLACK;
 221}
 222
 223void rb_erase(rb_node_t * node, rb_root_t * root)
 224{
 225        rb_node_t * child, * parent;
 226        int color;
 227
 228        if (!node->rb_left)
 229                child = node->rb_right;
 230        else if (!node->rb_right)
 231                child = node->rb_left;
 232        else
 233        {
 234                rb_node_t * old = node, * left;
 235
 236                node = node->rb_right;
 237                while ((left = node->rb_left))
 238                        node = left;
 239                child = node->rb_right;
 240                parent = node->rb_parent;
 241                color = node->rb_color;
 242
 243                if (child)
 244                        child->rb_parent = parent;
 245                if (parent)
 246                {
 247                        if (parent->rb_left == node)
 248                                parent->rb_left = child;
 249                        else
 250                                parent->rb_right = child;
 251                }
 252                else
 253                        root->rb_node = child;
 254
 255                if (node->rb_parent == old)
 256                        parent = node;
 257                node->rb_parent = old->rb_parent;
 258                node->rb_color = old->rb_color;
 259                node->rb_right = old->rb_right;
 260                node->rb_left = old->rb_left;
 261
 262                if (old->rb_parent)
 263                {
 264                        if (old->rb_parent->rb_left == old)
 265                                old->rb_parent->rb_left = node;
 266                        else
 267                                old->rb_parent->rb_right = node;
 268                } else
 269                        root->rb_node = node;
 270
 271                old->rb_left->rb_parent = node;
 272                if (old->rb_right)
 273                        old->rb_right->rb_parent = node;
 274                goto color;
 275        }
 276
 277        parent = node->rb_parent;
 278        color = node->rb_color;
 279
 280        if (child)
 281                child->rb_parent = parent;
 282        if (parent)
 283        {
 284                if (parent->rb_left == node)
 285                        parent->rb_left = child;
 286                else
 287                        parent->rb_right = child;
 288        }
 289        else
 290                root->rb_node = child;
 291
 292 color:
 293        if (color == RB_BLACK)
 294                __rb_erase_color(child, parent, root);
 295}
 296EXPORT_SYMBOL(rb_erase);
 297
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.