1
/* $Id: rbtree.c 3553 2011-05-05 06:14:19Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
#include <pj/rbtree.h>
23
static void left_rotate( pj_rbtree *tree, pj_rbtree_node *node )
25
pj_rbtree_node *rnode, *parent;
30
if (rnode == tree->null)
33
node->right = rnode->left;
34
if (rnode->left != tree->null)
35
rnode->left->parent = node;
36
parent = node->parent;
37
rnode->parent = parent;
38
if (parent != tree->null) {
39
if (parent->left == node)
42
parent->right = rnode;
50
static void right_rotate( pj_rbtree *tree, pj_rbtree_node *node )
52
pj_rbtree_node *lnode, *parent;
57
if (lnode == tree->null)
60
node->left = lnode->right;
61
if (lnode->right != tree->null)
62
lnode->right->parent = node;
63
parent = node->parent;
64
lnode->parent = parent;
66
if (parent != tree->null) {
67
if (parent->left == node)
70
parent->right = lnode;
78
static void insert_fixup( pj_rbtree *tree, pj_rbtree_node *node )
80
pj_rbtree_node *temp, *parent;
84
while (node != tree->root && node->parent->color == PJ_RBCOLOR_RED) {
85
parent = node->parent;
86
if (parent == parent->parent->left) {
87
temp = parent->parent->right;
88
if (temp->color == PJ_RBCOLOR_RED) {
89
temp->color = PJ_RBCOLOR_BLACK;
91
node->color = PJ_RBCOLOR_BLACK;
93
node->color = PJ_RBCOLOR_RED;
95
if (node == parent->right) {
97
left_rotate(tree, node);
100
temp->color = PJ_RBCOLOR_BLACK;
102
temp->color = PJ_RBCOLOR_RED;
103
right_rotate( tree, temp);
106
temp = parent->parent->left;
107
if (temp->color == PJ_RBCOLOR_RED) {
108
temp->color = PJ_RBCOLOR_BLACK;
110
node->color = PJ_RBCOLOR_BLACK;
112
node->color = PJ_RBCOLOR_RED;
114
if (node == parent->left) {
116
right_rotate(tree, node);
119
temp->color = PJ_RBCOLOR_BLACK;
121
temp->color = PJ_RBCOLOR_RED;
122
left_rotate(tree, temp);
127
tree->root->color = PJ_RBCOLOR_BLACK;
131
static void delete_fixup( pj_rbtree *tree, pj_rbtree_node *node )
133
pj_rbtree_node *temp;
137
while (node != tree->root && node->color == PJ_RBCOLOR_BLACK) {
138
if (node->parent->left == node) {
139
temp = node->parent->right;
140
if (temp->color == PJ_RBCOLOR_RED) {
141
temp->color = PJ_RBCOLOR_BLACK;
142
node->parent->color = PJ_RBCOLOR_RED;
143
left_rotate(tree, node->parent);
144
temp = node->parent->right;
146
if (temp->left->color == PJ_RBCOLOR_BLACK &&
147
temp->right->color == PJ_RBCOLOR_BLACK)
149
temp->color = PJ_RBCOLOR_RED;
152
if (temp->right->color == PJ_RBCOLOR_BLACK) {
153
temp->left->color = PJ_RBCOLOR_BLACK;
154
temp->color = PJ_RBCOLOR_RED;
155
right_rotate( tree, temp);
156
temp = node->parent->right;
158
temp->color = node->parent->color;
159
temp->right->color = PJ_RBCOLOR_BLACK;
160
node->parent->color = PJ_RBCOLOR_BLACK;
161
left_rotate(tree, node->parent);
165
temp = node->parent->left;
166
if (temp->color == PJ_RBCOLOR_RED) {
167
temp->color = PJ_RBCOLOR_BLACK;
168
node->parent->color = PJ_RBCOLOR_RED;
169
right_rotate( tree, node->parent);
170
temp = node->parent->left;
172
if (temp->right->color == PJ_RBCOLOR_BLACK &&
173
temp->left->color == PJ_RBCOLOR_BLACK)
175
temp->color = PJ_RBCOLOR_RED;
178
if (temp->left->color == PJ_RBCOLOR_BLACK) {
179
temp->right->color = PJ_RBCOLOR_BLACK;
180
temp->color = PJ_RBCOLOR_RED;
181
left_rotate( tree, temp);
182
temp = node->parent->left;
184
temp->color = node->parent->color;
185
node->parent->color = PJ_RBCOLOR_BLACK;
186
temp->left->color = PJ_RBCOLOR_BLACK;
187
right_rotate(tree, node->parent);
193
node->color = PJ_RBCOLOR_BLACK;
197
PJ_DEF(void) pj_rbtree_init( pj_rbtree *tree, pj_rbtree_comp *comp )
201
tree->null = tree->root = &tree->null_node;
202
tree->null->key = NULL;
203
tree->null->user_data = NULL;
205
tree->null->left = tree->null->right = tree->null->parent = tree->null;
206
tree->null->color = PJ_RBCOLOR_BLACK;
210
PJ_DEF(pj_rbtree_node*) pj_rbtree_first( pj_rbtree *tree )
212
register pj_rbtree_node *node = tree->root;
213
register pj_rbtree_node *null = tree->null;
217
while (node->left != null)
219
return node != null ? node : NULL;
222
PJ_DEF(pj_rbtree_node*) pj_rbtree_last( pj_rbtree *tree )
224
register pj_rbtree_node *node = tree->root;
225
register pj_rbtree_node *null = tree->null;
229
while (node->right != null)
231
return node != null ? node : NULL;
234
PJ_DEF(pj_rbtree_node*) pj_rbtree_next( pj_rbtree *tree,
235
register pj_rbtree_node *node )
237
register pj_rbtree_node *null = tree->null;
241
if (node->right != null) {
242
for (node=node->right; node->left!=null; node = node->left)
245
register pj_rbtree_node *temp = node->parent;
246
while (temp!=null && temp->right==node) {
252
return node != null ? node : NULL;
255
PJ_DEF(pj_rbtree_node*) pj_rbtree_prev( pj_rbtree *tree,
256
register pj_rbtree_node *node )
258
register pj_rbtree_node *null = tree->null;
262
if (node->left != null) {
263
for (node=node->left; node->right!=null; node=node->right)
266
register pj_rbtree_node *temp = node->parent;
267
while (temp!=null && temp->left==node) {
273
return node != null ? node : NULL;
276
PJ_DEF(int) pj_rbtree_insert( pj_rbtree *tree,
277
pj_rbtree_node *element )
280
pj_rbtree_node *node, *parent = tree->null,
282
pj_rbtree_comp *comp = tree->comp;
287
while (node != null) {
288
rv = (*comp)(element->key, node->key);
290
/* found match, i.e. entry with equal key already exist */
294
node = rv < 0 ? node->left : node->right;
297
element->color = PJ_RBCOLOR_RED;
298
element->left = element->right = null;
301
if (parent != null) {
302
node->parent = parent;
306
parent->right = node;
307
insert_fixup( tree, node);
311
node->color = PJ_RBCOLOR_BLACK;
319
PJ_DEF(pj_rbtree_node*) pj_rbtree_find( pj_rbtree *tree,
323
pj_rbtree_node *node = tree->root;
324
pj_rbtree_node *null = tree->null;
325
pj_rbtree_comp *comp = tree->comp;
327
while (node != null) {
328
rv = (*comp)(key, node->key);
331
node = rv < 0 ? node->left : node->right;
333
return node != null ? node : NULL;
336
PJ_DEF(pj_rbtree_node*) pj_rbtree_erase( pj_rbtree *tree,
337
pj_rbtree_node *node )
339
pj_rbtree_node *succ;
340
pj_rbtree_node *null = tree->null;
341
pj_rbtree_node *child;
342
pj_rbtree_node *parent;
346
if (node->left == null || node->right == null) {
349
for (succ=node->right; succ->left!=null; succ=succ->left)
353
child = succ->left != null ? succ->left : succ->right;
354
parent = succ->parent;
355
child->parent = parent;
357
if (parent != null) {
358
if (parent->left == succ)
359
parent->left = child;
361
parent->right = child;
366
succ->parent = node->parent;
367
succ->left = node->left;
368
succ->right = node->right;
369
succ->color = node->color;
371
parent = node->parent;
372
if (parent != null) {
373
if (parent->left==node)
378
if (node->left != null)
379
node->left->parent = succ;;
380
if (node->right != null)
381
node->right->parent = succ;
383
if (tree->root == node)
387
if (succ->color == PJ_RBCOLOR_BLACK) {
389
delete_fixup(tree, child);
390
tree->null->color = PJ_RBCOLOR_BLACK;
398
PJ_DEF(unsigned) pj_rbtree_max_height( pj_rbtree *tree,
399
pj_rbtree_node *node )
408
l = node->left != tree->null ? pj_rbtree_max_height(tree,node->left)+1 : 0;
409
r = node->right != tree->null ? pj_rbtree_max_height(tree,node->right)+1 : 0;
410
return l > r ? l : r;
413
PJ_DEF(unsigned) pj_rbtree_min_height( pj_rbtree *tree,
414
pj_rbtree_node *node )
423
l = (node->left != tree->null) ? pj_rbtree_max_height(tree,node->left)+1 : 0;
424
r = (node->right != tree->null) ? pj_rbtree_max_height(tree,node->right)+1 : 0;
425
return l > r ? r : l;