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