blob: 981bb6de3888b2edbab510a641c5427877296ccd [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
Benny Prijono844653c2008-12-23 17:27:53 +00003 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijono9033e312005-11-21 02:08:39 +00005 *
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.
10 *
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.
15 *
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
19 */
20#include <pj/rbtree.h>
21#include <pj/os.h>
22
23static void left_rotate( pj_rbtree *tree, pj_rbtree_node *node )
24{
25 pj_rbtree_node *rnode, *parent;
26
27 PJ_CHECK_STACK();
28
29 rnode = node->right;
30 if (rnode == tree->null)
31 return;
32
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)
40 parent->left = rnode;
41 else
42 parent->right = rnode;
43 } else {
44 tree->root = rnode;
45 }
46 rnode->left = node;
47 node->parent = rnode;
48}
49
50static void right_rotate( pj_rbtree *tree, pj_rbtree_node *node )
51{
52 pj_rbtree_node *lnode, *parent;
53
54 PJ_CHECK_STACK();
55
56 lnode = node->left;
57 if (lnode == tree->null)
58 return;
59
60 node->left = lnode->right;
61 if (lnode->right != tree->null)
62 lnode->right->parent = node;
63 parent = node->parent;
64 lnode->parent = parent;
65
66 if (parent != tree->null) {
67 if (parent->left == node)
68 parent->left = lnode;
69 else
70 parent->right = lnode;
71 } else {
72 tree->root = lnode;
73 }
74 lnode->right = node;
75 node->parent = lnode;
76}
77
78static void insert_fixup( pj_rbtree *tree, pj_rbtree_node *node )
79{
80 pj_rbtree_node *temp, *parent;
81
82 PJ_CHECK_STACK();
83
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;
90 node = parent;
91 node->color = PJ_RBCOLOR_BLACK;
92 node = node->parent;
93 node->color = PJ_RBCOLOR_RED;
94 } else {
95 if (node == parent->right) {
96 node = parent;
97 left_rotate(tree, node);
98 }
99 temp = node->parent;
100 temp->color = PJ_RBCOLOR_BLACK;
101 temp = temp->parent;
102 temp->color = PJ_RBCOLOR_RED;
103 right_rotate( tree, temp);
104 }
105 } else {
106 temp = parent->parent->left;
107 if (temp->color == PJ_RBCOLOR_RED) {
108 temp->color = PJ_RBCOLOR_BLACK;
109 node = parent;
110 node->color = PJ_RBCOLOR_BLACK;
111 node = node->parent;
112 node->color = PJ_RBCOLOR_RED;
113 } else {
114 if (node == parent->left) {
115 node = parent;
116 right_rotate(tree, node);
117 }
118 temp = node->parent;
119 temp->color = PJ_RBCOLOR_BLACK;
120 temp = temp->parent;
121 temp->color = PJ_RBCOLOR_RED;
122 left_rotate(tree, temp);
123 }
124 }
125 }
126
127 tree->root->color = PJ_RBCOLOR_BLACK;
128}
129
130
131static void delete_fixup( pj_rbtree *tree, pj_rbtree_node *node )
132{
133 pj_rbtree_node *temp;
134
135 PJ_CHECK_STACK();
136
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;
145 }
146 if (temp->left->color == PJ_RBCOLOR_BLACK &&
147 temp->right->color == PJ_RBCOLOR_BLACK)
148 {
149 temp->color = PJ_RBCOLOR_RED;
150 node = node->parent;
151 } else {
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;
157 }
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);
162 node = tree->root;
163 }
164 } else {
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;
171 }
172 if (temp->right->color == PJ_RBCOLOR_BLACK &&
173 temp->left->color == PJ_RBCOLOR_BLACK)
174 {
175 temp->color = PJ_RBCOLOR_RED;
176 node = node->parent;
177 } else {
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;
183 }
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);
188 node = tree->root;
189 }
190 }
191 }
192
193 node->color = PJ_RBCOLOR_BLACK;
194}
195
196
197PJ_DEF(void) pj_rbtree_init( pj_rbtree *tree, pj_rbtree_comp *comp )
198{
199 PJ_CHECK_STACK();
200
201 tree->null = tree->root = &tree->null_node;
202 tree->null->key = NULL;
203 tree->null->user_data = NULL;
204 tree->size = 0;
205 tree->null->left = tree->null->right = tree->null->parent = tree->null;
206 tree->null->color = PJ_RBCOLOR_BLACK;
207 tree->comp = comp;
208}
209
210PJ_DEF(pj_rbtree_node*) pj_rbtree_first( pj_rbtree *tree )
211{
212 register pj_rbtree_node *node = tree->root;
213 register pj_rbtree_node *null = tree->null;
214
215 PJ_CHECK_STACK();
216
217 while (node->left != null)
218 node = node->left;
219 return node != null ? node : NULL;
220}
221
222PJ_DEF(pj_rbtree_node*) pj_rbtree_last( pj_rbtree *tree )
223{
224 register pj_rbtree_node *node = tree->root;
225 register pj_rbtree_node *null = tree->null;
226
227 PJ_CHECK_STACK();
228
229 while (node->right != null)
230 node = node->right;
231 return node != null ? node : NULL;
232}
233
234PJ_DEF(pj_rbtree_node*) pj_rbtree_next( pj_rbtree *tree,
235 register pj_rbtree_node *node )
236{
237 register pj_rbtree_node *null = tree->null;
238
239 PJ_CHECK_STACK();
240
241 if (node->right != null) {
242 for (node=node->right; node->left!=null; node = node->left)
243 /* void */;
244 } else {
245 register pj_rbtree_node *temp = node->parent;
246 while (temp!=null && temp->right==node) {
247 node = temp;
248 temp = temp->parent;
249 }
250 node = temp;
251 }
252 return node != null ? node : NULL;
253}
254
255PJ_DEF(pj_rbtree_node*) pj_rbtree_prev( pj_rbtree *tree,
256 register pj_rbtree_node *node )
257{
258 register pj_rbtree_node *null = tree->null;
259
260 PJ_CHECK_STACK();
261
262 if (node->left != null) {
263 for (node=node->left; node->right!=null; node=node->right)
264 /* void */;
265 } else {
266 register pj_rbtree_node *temp = node->parent;
267 while (temp!=null && temp->left==node) {
268 node = temp;
269 temp = temp->parent;
270 }
271 node = temp;
272 }
273 return node != null ? node : NULL;
274}
275
276PJ_DEF(int) pj_rbtree_insert( pj_rbtree *tree,
277 pj_rbtree_node *element )
278{
279 int rv = 0;
280 pj_rbtree_node *node, *parent = tree->null,
281 *null = tree->null;
282 pj_rbtree_comp *comp = tree->comp;
283
284 PJ_CHECK_STACK();
285
286 node = tree->root;
287 while (node != null) {
288 rv = (*comp)(element->key, node->key);
289 if (rv == 0) {
290 /* found match, i.e. entry with equal key already exist */
291 return -1;
292 }
293 parent = node;
294 node = rv < 0 ? node->left : node->right;
295 }
296
297 element->color = PJ_RBCOLOR_RED;
298 element->left = element->right = null;
299
300 node = element;
301 if (parent != null) {
302 node->parent = parent;
303 if (rv < 0)
304 parent->left = node;
305 else
306 parent->right = node;
307 insert_fixup( tree, node);
308 } else {
309 tree->root = node;
310 node->parent = null;
311 node->color = PJ_RBCOLOR_BLACK;
312 }
313
314 ++tree->size;
315 return 0;
316}
317
318
319PJ_DEF(pj_rbtree_node*) pj_rbtree_find( pj_rbtree *tree,
320 const void *key )
321{
322 int rv;
323 pj_rbtree_node *node = tree->root;
324 pj_rbtree_node *null = tree->null;
325 pj_rbtree_comp *comp = tree->comp;
326
327 while (node != null) {
328 rv = (*comp)(key, node->key);
329 if (rv == 0)
330 return node;
331 node = rv < 0 ? node->left : node->right;
332 }
333 return node != null ? node : NULL;
334}
335
336PJ_DEF(pj_rbtree_node*) pj_rbtree_erase( pj_rbtree *tree,
337 pj_rbtree_node *node )
338{
339 pj_rbtree_node *succ;
340 pj_rbtree_node *null = tree->null;
341 pj_rbtree_node *child;
342 pj_rbtree_node *parent;
343
344 PJ_CHECK_STACK();
345
346 if (node->left == null || node->right == null) {
347 succ = node;
348 } else {
349 for (succ=node->right; succ->left!=null; succ=succ->left)
350 /* void */;
351 }
352
353 child = succ->left != null ? succ->left : succ->right;
354 parent = succ->parent;
355 child->parent = parent;
356
357 if (parent != null) {
358 if (parent->left == succ)
359 parent->left = child;
360 else
361 parent->right = child;
362 } else
363 tree->root = child;
364
365 if (succ != node) {
366 succ->parent = node->parent;
367 succ->left = node->left;
368 succ->right = node->right;
369 succ->color = node->color;
370
371 parent = node->parent;
372 if (parent != null) {
373 if (parent->left==node)
374 parent->left=succ;
375 else
376 parent->right=succ;
377 }
378 if (node->left != null)
379 node->left->parent = succ;;
380 if (node->right != null)
381 node->right->parent = succ;
382
383 if (tree->root == node)
384 tree->root = succ;
385 }
386
387 if (succ->color == PJ_RBCOLOR_BLACK) {
388 if (child != null)
389 delete_fixup(tree, child);
390 tree->null->color = PJ_RBCOLOR_BLACK;
391 }
392
393 --tree->size;
394 return node;
395}
396
397
398PJ_DEF(unsigned) pj_rbtree_max_height( pj_rbtree *tree,
399 pj_rbtree_node *node )
400{
401 unsigned l, r;
402
403 PJ_CHECK_STACK();
404
405 if (node==NULL)
406 node = tree->root;
407
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;
411}
412
413PJ_DEF(unsigned) pj_rbtree_min_height( pj_rbtree *tree,
414 pj_rbtree_node *node )
415{
416 unsigned l, r;
417
418 PJ_CHECK_STACK();
419
420 if (node==NULL)
421 node=tree->root;
422
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;
426}
427
428