2 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #include "gtkrbtree.h"
22 static void _gtk_rbnode_validate_allocator (GAllocator *allocator);
23 static GtkRBNode *_gtk_rbnode_new (GtkRBTree *tree,
25 static void _gtk_rbnode_free (GtkRBNode *node);
26 static void _gtk_rbnode_rotate_left (GtkRBTree *tree,
28 static void _gtk_rbnode_rotate_left (GtkRBTree *tree,
30 static void _gtk_rbtree_insert_fixup (GtkRBTree *tree,
32 static void _gtk_rbtree_remove_node_fixup (GtkRBTree *tree,
34 static gint _count_nodes (GtkRBTree *tree,
40 struct _GAllocator /* from gmem.c */
48 GtkRBNode *free_nodes; /* implementation specific */
52 G_LOCK_DEFINE_STATIC (current_allocator);
53 static GAllocator *current_allocator = NULL;
55 /* HOLDS: current_allocator_lock */
57 _gtk_rbnode_validate_allocator (GAllocator *allocator)
59 g_return_if_fail (allocator != NULL);
60 g_return_if_fail (allocator->is_unused == TRUE);
62 if (allocator->type != G_ALLOCATOR_NODE)
64 allocator->type = G_ALLOCATOR_NODE;
65 if (allocator->mem_chunk)
67 g_mem_chunk_destroy (allocator->mem_chunk);
68 allocator->mem_chunk = NULL;
72 if (!allocator->mem_chunk)
74 allocator->mem_chunk = g_mem_chunk_new (allocator->name,
76 sizeof (GtkRBNode) * allocator->n_preallocs,
78 allocator->free_nodes = NULL;
81 allocator->is_unused = FALSE;
85 _gtk_rbnode_new (GtkRBTree *tree,
90 G_LOCK (current_allocator);
91 if (!current_allocator)
93 GAllocator *allocator = g_allocator_new ("GTK+ default GtkRBNode allocator",
95 _gtk_rbnode_validate_allocator (allocator);
96 allocator->last = NULL;
97 current_allocator = allocator;
99 if (!current_allocator->free_nodes)
100 node = g_chunk_new (GtkRBNode, current_allocator->mem_chunk);
103 node = current_allocator->free_nodes;
104 current_allocator->free_nodes = node->left;
106 G_UNLOCK (current_allocator);
108 node->left = tree->nil;
109 node->right = tree->nil;
110 node->parent = tree->nil;
111 node->flags = GTK_RBNODE_RED;
113 node->children = NULL;
114 node->offset = height;
119 _gtk_rbnode_free (GtkRBNode *node)
121 G_LOCK (current_allocator);
122 node->left = current_allocator->free_nodes;
123 current_allocator->free_nodes = node;
124 G_UNLOCK (current_allocator);
128 _gtk_rbnode_rotate_left (GtkRBTree *tree,
131 gint node_height, right_height;
132 GtkRBNode *right = node->right;
134 g_return_if_fail (node != tree->nil);
136 node_height = node->offset -
137 (node->left?node->left->offset:0) -
138 (node->right?node->right->offset:0) -
139 (node->children?node->children->root->offset:0);
140 right_height = right->offset -
141 (right->left?right->left->offset:0) -
142 (right->right?right->right->offset:0) -
143 (right->children?right->children->root->offset:0);
145 node->right = right->left;
146 if (right->left != tree->nil)
147 right->left->parent = node;
149 if (right != tree->nil)
150 right->parent = node->parent;
151 if (node->parent != tree->nil)
153 if (node == node->parent->left)
154 node->parent->left = right;
156 node->parent->right = right;
162 if (node != tree->nil)
163 node->parent = right;
165 node->count = 1 + (node->left?node->left->count:0) +
166 (node->right?node->right->count:0);
167 right->count = 1 + (right->left?right->left->count:0) +
168 (right->right?right->right->count:0);
169 node->offset = node_height +
170 (node->left?node->left->offset:0) +
171 (node->right?node->right->offset:0) +
172 (node->children?node->children->root->offset:0);
173 right->offset = right_height +
174 (right->left?right->left->offset:0) +
175 (right->right?right->right->offset:0) +
176 (right->children?right->children->root->offset:0);
180 _gtk_rbnode_rotate_right (GtkRBTree *tree,
183 gint node_height, left_height;
184 GtkRBNode *left = node->left;
186 g_return_if_fail (node != tree->nil);
188 node_height = node->offset -
189 (node->left?node->left->offset:0) -
190 (node->right?node->right->offset:0) -
191 (node->children?node->children->root->offset:0);
192 left_height = left->offset -
193 (left->left?left->left->offset:0) -
194 (left->right?left->right->offset:0) -
195 (left->children?left->children->root->offset:0);
197 node->left = left->right;
198 if (left->right != tree->nil)
199 left->right->parent = node;
201 if (left != tree->nil)
202 left->parent = node->parent;
203 if (node->parent != tree->nil)
205 if (node == node->parent->right)
206 node->parent->right = left;
208 node->parent->left = left;
215 /* link node and left */
217 if (node != tree->nil)
220 node->count = 1 + (node->left?node->left->count:0) +
221 (node->right?node->right->count:0);
222 left->count = 1 + (left->left?left->left->count:0) +
223 (left->right?left->right->count:0);
224 node->offset = node_height +
225 (node->left?node->left->offset:0) +
226 (node->right?node->right->offset:0) +
227 (node->children?node->children->root->offset:0);
228 left->offset = left_height +
229 (left->left?left->left->offset:0) +
230 (left->right?left->right->offset:0) +
231 (left->children?left->children->root->offset:0);
235 _gtk_rbtree_insert_fixup (GtkRBTree *tree,
239 /* check Red-Black properties */
240 while (node != tree->root && GTK_RBNODE_GET_COLOR (node->parent) == GTK_RBNODE_RED)
242 /* we have a violation */
243 if (node->parent == node->parent->parent->left)
245 GtkRBNode *y = node->parent->parent->right;
246 if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_RED)
248 /* uncle is GTK_RBNODE_RED */
249 GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
250 GTK_RBNODE_SET_COLOR (y, GTK_RBNODE_BLACK);
251 GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
252 node = node->parent->parent;
256 /* uncle is GTK_RBNODE_BLACK */
257 if (node == node->parent->right)
259 /* make node a left child */
261 _gtk_rbnode_rotate_left (tree, node);
264 /* recolor and rotate */
265 GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
266 GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
267 _gtk_rbnode_rotate_right(tree, node->parent->parent);
272 /* mirror image of above code */
273 GtkRBNode *y = node->parent->parent->left;
274 if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_RED)
276 /* uncle is GTK_RBNODE_RED */
277 GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
278 GTK_RBNODE_SET_COLOR (y, GTK_RBNODE_BLACK);
279 GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
280 node = node->parent->parent;
284 /* uncle is GTK_RBNODE_BLACK */
285 if (node == node->parent->left)
288 _gtk_rbnode_rotate_right (tree, node);
290 GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
291 GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
292 _gtk_rbnode_rotate_left (tree, node->parent->parent);
296 GTK_RBNODE_SET_COLOR (tree->root, GTK_RBNODE_BLACK);
300 _gtk_rbtree_remove_node_fixup (GtkRBTree *tree,
303 while (node != tree->root && GTK_RBNODE_GET_COLOR (node) == GTK_RBNODE_BLACK)
305 if (node == node->parent->left)
307 GtkRBNode *w = node->parent->right;
308 if (GTK_RBNODE_GET_COLOR (w) == GTK_RBNODE_RED)
310 GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_BLACK);
311 GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_RED);
312 _gtk_rbnode_rotate_left (tree, node->parent);
313 w = node->parent->right;
315 if (GTK_RBNODE_GET_COLOR (w->left) == GTK_RBNODE_BLACK && GTK_RBNODE_GET_COLOR (w->right) == GTK_RBNODE_BLACK)
317 GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
322 if (GTK_RBNODE_GET_COLOR (w->right) == GTK_RBNODE_BLACK)
324 GTK_RBNODE_SET_COLOR (w->left, GTK_RBNODE_BLACK);
325 GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
326 _gtk_rbnode_rotate_right (tree, w);
327 w = node->parent->right;
329 GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_GET_COLOR (node->parent));
330 GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
331 GTK_RBNODE_SET_COLOR (w->right, GTK_RBNODE_BLACK);
332 _gtk_rbnode_rotate_left (tree, node->parent);
338 GtkRBNode *w = node->parent->left;
339 if (GTK_RBNODE_GET_COLOR (w) == GTK_RBNODE_RED)
341 GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_BLACK);
342 GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_RED);
343 _gtk_rbnode_rotate_right (tree, node->parent);
344 w = node->parent->left;
346 if (GTK_RBNODE_GET_COLOR (w->right) == GTK_RBNODE_BLACK && GTK_RBNODE_GET_COLOR (w->left) == GTK_RBNODE_BLACK)
348 GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
353 if (GTK_RBNODE_GET_COLOR (w->left) == GTK_RBNODE_BLACK)
355 GTK_RBNODE_SET_COLOR (w->right, GTK_RBNODE_BLACK);
356 GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
357 _gtk_rbnode_rotate_left (tree, w);
358 w = node->parent->left;
360 GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_GET_COLOR (node->parent));
361 GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
362 GTK_RBNODE_SET_COLOR (w->left, GTK_RBNODE_BLACK);
363 _gtk_rbnode_rotate_right (tree, node->parent);
368 GTK_RBNODE_SET_COLOR (node, GTK_RBNODE_BLACK);
371 /* Public functions */
373 _gtk_rbnode_push_allocator (GAllocator *allocator)
375 G_LOCK (current_allocator);
376 _gtk_rbnode_validate_allocator ( allocator );
377 allocator->last = current_allocator;
378 current_allocator = allocator;
379 G_UNLOCK (current_allocator);
383 _gtk_rbnode_pop_allocator (void)
385 G_LOCK (current_allocator);
386 if (current_allocator)
388 GAllocator *allocator;
390 allocator = current_allocator;
391 current_allocator = allocator->last;
392 allocator->last = NULL;
393 allocator->is_unused = TRUE;
395 G_UNLOCK (current_allocator);
399 _gtk_rbtree_new (void)
403 retval = (GtkRBTree *) g_new (GtkRBTree, 1);
404 retval->parent_tree = NULL;
405 retval->parent_node = NULL;
407 retval->nil = g_new0 (GtkRBNode, 1);
408 retval->nil->left = NULL;
409 retval->nil->right = NULL;
410 retval->nil->parent = NULL;
411 retval->nil->flags = GTK_RBNODE_BLACK;
412 retval->nil->count = 0;
413 retval->nil->offset = 0;
415 retval->root = retval->nil;
420 _gtk_rbtree_free_helper (GtkRBTree *tree,
425 _gtk_rbtree_free (node->children);
427 _gtk_rbnode_free (node);
431 _gtk_rbtree_free (GtkRBTree *tree)
433 _gtk_rbtree_traverse (tree,
436 _gtk_rbtree_free_helper,
439 if (tree->parent_node &&
440 tree->parent_node->children == tree)
441 tree->parent_node->children = NULL;
442 _gtk_rbnode_free (tree->nil);
447 _gtk_rbtree_remove (GtkRBTree *tree)
452 gint height = tree->root->offset;
453 tmp_tree = tree->parent_tree;
454 tmp_node = tree->parent_node;
456 while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
458 tmp_node->offset -= height;
459 tmp_node = tmp_node->parent;
460 if (tmp_node == tmp_tree->nil)
462 tmp_node = tmp_tree->parent_node;
463 tmp_tree = tmp_tree->parent_tree;
466 _gtk_rbtree_free (tree);
471 _gtk_rbtree_insert_after (GtkRBTree *tree,
476 gboolean right = TRUE;
480 if (current != NULL && current->right != tree->nil)
482 current = current->right;
483 while (current->left != tree->nil)
484 current = current->left;
489 node = _gtk_rbnode_new (tree, height);
490 node->parent = (current?current:tree->nil);
492 /* insert node in tree */
496 current->right = node;
498 current->left = node;
499 tmp_node = node->parent;
505 tmp_node = tree->parent_node;
506 tmp_tree = tree->parent_tree;
509 while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
511 /* We only want to propagate the count if we are in the tree we
513 if (tmp_tree == tree)
515 tmp_node->offset += height;
516 tmp_node = tmp_node->parent;
517 if (tmp_node == tmp_tree->nil)
519 tmp_node = tmp_tree->parent_node;
520 tmp_tree = tmp_tree->parent_tree;
523 _gtk_rbtree_insert_fixup (tree, node);
529 _gtk_rbtree_insert_before (GtkRBTree *tree,
534 gboolean left = TRUE;
538 if (current != NULL && current->left != tree->nil)
540 current = current->left;
541 while (current->right != tree->nil)
542 current = current->right;
547 node = _gtk_rbnode_new (tree, height);
548 node->parent = (current?current:tree->nil);
550 /* insert node in tree */
554 current->left = node;
556 current->right = node;
557 tmp_node = node->parent;
563 tmp_node = tree->parent_node;
564 tmp_tree = tree->parent_tree;
567 while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
569 /* We only want to propagate the count if we are in the tree we
571 if (tmp_tree == tree)
573 tmp_node->offset += height;
574 tmp_node = tmp_node->parent;
575 if (tmp_node == tmp_tree->nil)
577 tmp_node = tmp_tree->parent_node;
578 tmp_tree = tmp_tree->parent_tree;
581 _gtk_rbtree_insert_fixup (tree, node);
587 _gtk_rbtree_find_count (GtkRBTree *tree,
593 while (node != tree->nil && (node->left->count + 1 != count))
595 if (node->left->count >= count)
599 count -= (node->left->count + 1);
603 if (node == tree->nil)
609 _gtk_rbtree_node_set_height (GtkRBTree *tree,
613 gint diff = height - GTK_RBNODE_GET_HEIGHT (node);
614 GtkRBNode *tmp_node = node;
615 GtkRBTree *tmp_tree = tree;
620 while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
622 tmp_node->offset += diff;
623 tmp_node = tmp_node->parent;
624 if (tmp_node == tmp_tree->nil)
626 tmp_node = tmp_tree->parent_node;
627 tmp_tree = tmp_tree->parent_tree;
633 _gtk_rbtree_node_find_offset (GtkRBTree *tree,
637 gint retval = node->left->offset;
639 while (tree && node && node != tree->nil)
643 if (node->right == last)
644 retval += node->left->offset + GTK_RBNODE_GET_HEIGHT (node);
645 if (node == tree->nil)
647 node = tree->parent_node;
648 tree = tree->parent_tree;
650 retval += node->left->offset;
657 _gtk_rbtree_find_offset (GtkRBTree *tree,
659 GtkRBTree **new_tree,
660 GtkRBNode **new_node)
671 tmp_node = tree->root;
672 while (tmp_node != tree->nil &&
673 (tmp_node->left->offset > height ||
674 (tmp_node->offset - tmp_node->right->offset) < height))
676 if (tmp_node->left->offset > height)
677 tmp_node = tmp_node->left;
680 height -= (tmp_node->offset - tmp_node->right->offset);
681 tmp_node = tmp_node->right;
684 if (tmp_node == tree->nil)
690 if (tmp_node->children)
692 if ((tmp_node->offset -
693 tmp_node->right->offset -
694 tmp_node->children->root->offset) > height)
697 *new_node = tmp_node;
698 return (height - tmp_node->left->offset);
700 return _gtk_rbtree_find_offset (tmp_node->children,
701 height - tmp_node->left->offset -
703 tmp_node->left->offset -
704 tmp_node->right->offset -
705 tmp_node->children->root->offset),
710 *new_node = tmp_node;
711 return (height - tmp_node->left->offset);
716 _gtk_rbtree_remove_node (GtkRBTree *tree,
721 g_return_if_fail (tree != NULL);
722 g_return_if_fail (node != NULL);
723 /* make sure we're deleting a node that's actually in the tree */
724 for (x = node; x->parent != tree->nil; x = x->parent)
726 g_return_if_fail (x == tree->root);
728 if (node->left == tree->nil || node->right == tree->nil)
736 while (y->left != tree->nil)
739 for (x = y; x != tree->nil; x = x->parent)
741 y->count = node->count;
742 /* x is y's only child */
743 if (y->left != tree->nil)
748 /* remove y from the parent chain */
749 x->parent = y->parent;
750 if (y->parent != tree->nil)
751 if (y == y->parent->left)
754 y->parent->right = x;
759 node->children = y->children;
761 if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_BLACK)
762 _gtk_rbtree_remove_node_fixup (tree, x);
764 G_LOCK (current_allocator);
765 y->left = current_allocator->free_nodes;
766 current_allocator->free_nodes = y;
767 G_UNLOCK (current_allocator);
771 _gtk_rbtree_next (GtkRBTree *tree,
774 g_return_val_if_fail (tree != NULL, NULL);
775 g_return_val_if_fail (node != NULL, NULL);
777 /* Case 1: the node's below us. */
778 if (node->right != tree->nil)
781 while (node->left != tree->nil)
786 /* Case 2: it's an ancestor */
787 while (node->parent != tree->nil)
789 if (node->parent->right == node)
792 return (node->parent);
795 /* Case 3: There is no next node */
800 _gtk_rbtree_prev (GtkRBTree *tree,
803 g_return_val_if_fail (tree != NULL, NULL);
804 g_return_val_if_fail (node != NULL, NULL);
806 /* Case 1: the node's below us. */
807 if (node->left != tree->nil)
810 while (node->right != tree->nil)
815 /* Case 2: it's an ancestor */
816 while (node->parent != tree->nil)
818 if (node->parent->left == node)
821 return (node->parent);
824 /* Case 3: There is no next node */
829 _gtk_rbtree_next_full (GtkRBTree *tree,
831 GtkRBTree **new_tree,
832 GtkRBNode **new_node)
834 g_return_if_fail (tree != NULL);
835 g_return_if_fail (node != NULL);
836 g_return_if_fail (new_tree != NULL);
837 g_return_if_fail (new_node != NULL);
841 *new_tree = node->children;
842 *new_node = (*new_tree)->root;
843 while ((*new_node)->left != (*new_tree)->nil)
844 *new_node = (*new_node)->left;
849 *new_node = _gtk_rbtree_next (tree, node);
851 while ((*new_node == NULL) &&
854 *new_node = (*new_tree)->parent_node;
855 *new_tree = (*new_tree)->parent_tree;
857 *new_node = _gtk_rbtree_next (*new_tree, *new_node);
862 _gtk_rbtree_prev_full (GtkRBTree *tree,
864 GtkRBTree **new_tree,
865 GtkRBNode **new_node)
867 g_return_if_fail (tree != NULL);
868 g_return_if_fail (node != NULL);
869 g_return_if_fail (new_tree != NULL);
870 g_return_if_fail (new_node != NULL);
873 *new_node = _gtk_rbtree_prev (tree, node);
875 if (*new_node == NULL)
877 *new_node = (*new_tree)->parent_node;
878 *new_tree = (*new_tree)->parent_tree;
882 while ((*new_node)->children)
884 *new_tree = (*new_node)->children;
885 *new_node = (*new_tree)->root;
886 while ((*new_node)->right != (*new_tree)->nil)
887 *new_node = (*new_node)->right;
893 _gtk_rbtree_traverse_pre_order (GtkRBTree *tree,
895 GtkRBTreeTraverseFunc func,
898 if (node == tree->nil)
901 (* func) (tree, node, data);
902 _gtk_rbtree_traverse_pre_order (tree, node->left, func, data);
903 _gtk_rbtree_traverse_pre_order (tree, node->right, func, data);
907 _gtk_rbtree_traverse_post_order (GtkRBTree *tree,
909 GtkRBTreeTraverseFunc func,
912 if (node == tree->nil)
915 _gtk_rbtree_traverse_post_order (tree, node->left, func, data);
916 _gtk_rbtree_traverse_post_order (tree, node->right, func, data);
917 (* func) (tree, node, data);
921 _gtk_rbtree_traverse (GtkRBTree *tree,
924 GtkRBTreeTraverseFunc func,
927 g_return_if_fail (tree != NULL);
928 g_return_if_fail (node != NULL);
929 g_return_if_fail (func != NULL);
930 g_return_if_fail (order <= G_LEVEL_ORDER);
935 _gtk_rbtree_traverse_pre_order (tree, node, func, data);
938 _gtk_rbtree_traverse_post_order (tree, node, func, data);
943 g_warning ("unsupported traversal order.");
949 _count_nodes (GtkRBTree *tree,
953 if (node == tree->nil)
956 res = (_count_nodes (tree, node->left) +
957 _count_nodes (tree, node->right) + 1);
959 if (res != node->count)
960 g_print ("Tree failed\n");
965 _gtk_rbtree_test (GtkRBTree *tree)
967 if ((_count_nodes (tree, tree->root->left) +
968 _count_nodes (tree, tree->root->right) + 1) == tree->root->count)
969 g_print ("Tree passed\n");
971 g_print ("Tree failed\n");
976 _gtk_rbtree_test_height_helper (GtkRBTree *tree,
980 if (node == tree->nil)
984 (node->left?node->left->offset:0) -
985 (node->right?node->right->offset:0) -
986 (node->children?node->children->root->offset:0) != height)
987 g_error ("tree failed\n");
989 _gtk_rbtree_test_height_helper (tree, node->left, height);
990 _gtk_rbtree_test_height_helper (tree, node->right, height);
992 _gtk_rbtree_test_height_helper (node->children, node->children->root, height);
997 _gtk_rbtree_test_height (GtkRBTree *tree,
1000 _gtk_rbtree_test_height_helper (tree, tree->root, height);