1 /* Sequential list data type implemented by a binary tree.
2 Copyright (C) 2006 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2006.
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, or (at your option)
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.
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 Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19 /* Common code of gl_avltree_list.c and gl_avltreehash_list.c. */
21 /* -------------------------- gl_list_t Data Type -------------------------- */
23 /* Create a subtree for count >= 1 elements.
24 Its height is h where 2^(h-1) <= count <= 2^h - 1. */
26 create_subtree_with_contents (size_t count, const void **contents)
28 size_t half1 = (count - 1) / 2;
29 size_t half2 = count / 2;
30 /* Note: half1 + half2 = count - 1. */
32 (struct gl_list_node_impl *) xmalloc (sizeof (struct gl_list_node_impl));
36 node->left = create_subtree_with_contents (half1, contents);
37 node->left->parent = node;
42 node->value = contents[half1];
46 node->right = create_subtree_with_contents (half2, contents + half1 + 1);
47 node->right->parent = node;
52 /* balance is 0, except when count is a power of two and > 1.
53 Reason: half1 <= half2 <= half1 + 1, and the two branches can have
54 different heights only if half1 = 2^h - 1 and half2 = 2^h; in this
55 case, count = half1 + half2 + 1 = 2^(h+1). */
56 node->balance = (count > 1 && (count & (count - 1)) == 0 ? 1 : 0);
58 node->branch_size = count;
64 gl_tree_create (gl_list_implementation_t implementation,
65 gl_listelement_equals_fn equals_fn,
66 gl_listelement_hashcode_fn hashcode_fn,
67 bool allow_duplicates,
68 size_t count, const void **contents)
70 struct gl_list_impl *list =
71 (struct gl_list_impl *) xmalloc (sizeof (struct gl_list_impl));
73 list->base.vtable = implementation;
74 list->base.equals_fn = equals_fn;
75 list->base.hashcode_fn = hashcode_fn;
76 list->base.allow_duplicates = allow_duplicates;
79 size_t estimate = xsum (count, count / 2); /* 1.5 * count */
82 list->table_size = next_prime (estimate);
84 (gl_hash_entry_t *) xzalloc (list->table_size * sizeof (gl_hash_entry_t));
89 list->root = create_subtree_with_contents (count, contents);
90 list->root->parent = NULL;
93 /* Now that the tree is built, node_position() works. Now we can
94 add the nodes to the hash table. */
95 add_nodes_to_buckets (list);
104 /* Ensure the tree is balanced, after an insertion or deletion operation.
105 The height of NODE is incremented by HEIGHT_DIFF (1 or -1).
106 PARENT = NODE->parent. (NODE can also be NULL. But PARENT is non-NULL.)
107 Rotation operations are performed starting at PARENT (not NODE itself!). */
109 rebalance (gl_list_t list,
110 gl_list_node_t node, int height_diff, gl_list_node_t parent)
114 gl_list_node_t child;
115 int previous_balance;
117 gl_list_node_t nodeleft;
118 gl_list_node_t noderight;
123 previous_balance = node->balance;
125 /* The balance of NODE is incremented by BALANCE_DIFF: +1 if the right
126 branch's height has increased by 1 or the left branch's height has
127 decreased by 1, -1 if the right branch's height has decreased by 1 or
128 the left branch's height has increased by 1, 0 if no height change. */
129 if (node->left != NULL || node->right != NULL)
130 balance_diff = (child == node->right ? height_diff : -height_diff);
132 /* Special case where above formula doesn't work, because the caller
133 didn't tell whether node's left or right branch shrunk from height 1
135 balance_diff = - previous_balance;
137 node->balance += balance_diff;
138 if (balance_diff == previous_balance)
140 /* node->balance is outside the range [-1,1]. Must rotate. */
141 gl_list_node_t *nodep;
143 if (node->parent == NULL)
144 /* node == list->root */
146 else if (node->parent->left == node)
147 nodep = &node->parent->left;
148 else if (node->parent->right == node)
149 nodep = &node->parent->right;
153 nodeleft = node->left;
154 noderight = node->right;
156 if (balance_diff < 0)
158 /* node->balance = -2. The subtree is heavier on the left side.
159 Rotate from left to right:
165 gl_list_node_t nodeleftleft = nodeleft->left;
166 gl_list_node_t nodeleftright = nodeleft->right;
167 if (nodeleft->balance <= 0)
174 h+1 h|h+1 h+1 h|h+1 h
176 node->left = nodeleftright;
177 nodeleft->right = node;
179 nodeleft->parent = node->parent;
180 node->parent = nodeleft;
181 if (nodeleftright != NULL)
182 nodeleftright->parent = node;
184 nodeleft->balance += 1;
185 node->balance = - nodeleft->balance;
188 (nodeleftright != NULL ? nodeleftright->branch_size : 0)
189 + 1 + (noderight != NULL ? noderight->branch_size : 0);
190 nodeleft->branch_size =
191 nodeleftleft->branch_size + 1 + node->branch_size;
194 height_diff = (height_diff < 0
195 ? /* noderight's height had been decremented from
196 h+1 to h. The subtree's height changes from
198 nodeleft->balance - 1
199 : /* nodeleft's height had been incremented from
200 h+1 to h+2. The subtree's height changes from
216 gl_list_node_t L = nodeleft->right = nodeleftright->left;
217 gl_list_node_t R = node->left = nodeleftright->right;
218 nodeleftright->left = nodeleft;
219 nodeleftright->right = node;
221 nodeleftright->parent = node->parent;
223 L->parent = nodeleft;
226 nodeleft->parent = nodeleftright;
227 node->parent = nodeleftright;
229 nodeleft->balance = (nodeleftright->balance > 0 ? -1 : 0);
230 node->balance = (nodeleftright->balance < 0 ? 1 : 0);
231 nodeleftright->balance = 0;
233 nodeleft->branch_size =
234 (nodeleft->left != NULL ? nodeleft->left->branch_size : 0)
235 + 1 + (nodeleft->right != NULL ? nodeleft->right->branch_size : 0);
237 (node->left != NULL ? node->left->branch_size : 0)
238 + 1 + (node->right != NULL ? node->right->branch_size : 0);
239 nodeleftright->branch_size =
240 nodeleft->branch_size + 1 + node->branch_size;
242 *nodep = nodeleftright;
243 height_diff = (height_diff < 0
244 ? /* noderight's height had been decremented from
245 h+1 to h. The subtree's height changes from
248 : /* nodeleft's height had been incremented from
249 h+1 to h+2. The subtree's height changes from
256 /* node->balance = 2. The subtree is heavier on the right side.
257 Rotate from right to left:
263 gl_list_node_t noderightleft = noderight->left;
264 gl_list_node_t noderightright = noderight->right;
265 if (noderight->balance >= 0)
272 h|h+1 h+1 h h|h+1 h+1
274 node->right = noderightleft;
275 noderight->left = node;
277 noderight->parent = node->parent;
278 node->parent = noderight;
279 if (noderightleft != NULL)
280 noderightleft->parent = node;
282 noderight->balance -= 1;
283 node->balance = - noderight->balance;
286 (nodeleft != NULL ? nodeleft->branch_size : 0)
287 + 1 + (noderightleft != NULL ? noderightleft->branch_size : 0);
288 noderight->branch_size =
289 node->branch_size + 1 + noderightright->branch_size;
292 height_diff = (height_diff < 0
293 ? /* nodeleft's height had been decremented from
294 h+1 to h. The subtree's height changes from
296 - noderight->balance - 1
297 : /* noderight's height had been incremented from
298 h+1 to h+2. The subtree's height changes from
300 - noderight->balance);
314 gl_list_node_t L = node->right = noderightleft->left;
315 gl_list_node_t R = noderight->left = noderightleft->right;
316 noderightleft->left = node;
317 noderightleft->right = noderight;
319 noderightleft->parent = node->parent;
323 R->parent = noderight;
324 node->parent = noderightleft;
325 noderight->parent = noderightleft;
327 node->balance = (noderightleft->balance > 0 ? -1 : 0);
328 noderight->balance = (noderightleft->balance < 0 ? 1 : 0);
329 noderightleft->balance = 0;
332 (node->left != NULL ? node->left->branch_size : 0)
333 + 1 + (node->right != NULL ? node->right->branch_size : 0);
334 noderight->branch_size =
335 (noderight->left != NULL ? noderight->left->branch_size : 0)
336 + 1 + (noderight->right != NULL ? noderight->right->branch_size : 0);
337 noderightleft->branch_size =
338 node->branch_size + 1 + noderight->branch_size;
340 *nodep = noderightleft;
341 height_diff = (height_diff < 0
342 ? /* nodeleft's height had been decremented from
343 h+1 to h. The subtree's height changes from
346 : /* noderight's height had been incremented from
347 h+1 to h+2. The subtree's height changes from
356 /* No rotation needed. Only propagation of the height change to the
357 next higher level. */
359 height_diff = (previous_balance == 0 ? 0 : -1);
361 height_diff = (node->balance == 0 ? 0 : 1);
364 if (height_diff == 0)
367 parent = node->parent;
373 static gl_list_node_t
374 gl_tree_add_first (gl_list_t list, const void *elt)
376 /* Create new node. */
377 gl_list_node_t new_node =
378 (struct gl_list_node_impl *) xmalloc (sizeof (struct gl_list_node_impl));
380 new_node->left = NULL;
381 new_node->right = NULL;
382 new_node->balance = 0;
383 new_node->branch_size = 1;
384 new_node->value = elt;
386 new_node->h.hashcode =
387 (list->base.hashcode_fn != NULL
388 ? list->base.hashcode_fn (new_node->value)
389 : (size_t)(uintptr_t) new_node->value);
392 /* Add it to the tree. */
393 if (list->root == NULL)
395 list->root = new_node;
396 new_node->parent = NULL;
402 for (node = list->root; node->left != NULL; )
405 node->left = new_node;
406 new_node->parent = node;
409 /* Update branch_size fields of the parent nodes. */
413 for (p = node; p != NULL; p = p->parent)
418 if (node->right == NULL && node->parent != NULL)
419 rebalance (list, node, 1, node->parent);
423 /* Add node to the hash table.
424 Note that this is only possible _after_ the node has been added to the
425 tree structure, because add_to_bucket() uses node_position(). */
426 add_to_bucket (list, new_node);
427 hash_resize_after_add (list);
433 static gl_list_node_t
434 gl_tree_add_last (gl_list_t list, const void *elt)
436 /* Create new node. */
437 gl_list_node_t new_node =
438 (struct gl_list_node_impl *) xmalloc (sizeof (struct gl_list_node_impl));
440 new_node->left = NULL;
441 new_node->right = NULL;
442 new_node->balance = 0;
443 new_node->branch_size = 1;
444 new_node->value = elt;
446 new_node->h.hashcode =
447 (list->base.hashcode_fn != NULL
448 ? list->base.hashcode_fn (new_node->value)
449 : (size_t)(uintptr_t) new_node->value);
452 /* Add it to the tree. */
453 if (list->root == NULL)
455 list->root = new_node;
456 new_node->parent = NULL;
462 for (node = list->root; node->right != NULL; )
465 node->right = new_node;
466 new_node->parent = node;
469 /* Update branch_size fields of the parent nodes. */
473 for (p = node; p != NULL; p = p->parent)
478 if (node->left == NULL && node->parent != NULL)
479 rebalance (list, node, 1, node->parent);
483 /* Add node to the hash table.
484 Note that this is only possible _after_ the node has been added to the
485 tree structure, because add_to_bucket() uses node_position(). */
486 add_to_bucket (list, new_node);
487 hash_resize_after_add (list);
493 static gl_list_node_t
494 gl_tree_add_before (gl_list_t list, gl_list_node_t node, const void *elt)
496 /* Create new node. */
497 gl_list_node_t new_node =
498 (struct gl_list_node_impl *) xmalloc (sizeof (struct gl_list_node_impl));
501 new_node->left = NULL;
502 new_node->right = NULL;
503 new_node->balance = 0;
504 new_node->branch_size = 1;
505 new_node->value = elt;
507 new_node->h.hashcode =
508 (list->base.hashcode_fn != NULL
509 ? list->base.hashcode_fn (new_node->value)
510 : (size_t)(uintptr_t) new_node->value);
513 /* Add it to the tree. */
514 if (node->left == NULL)
516 node->left = new_node;
518 height_inc = (node->right == NULL);
522 for (node = node->left; node->right != NULL; )
524 node->right = new_node;
526 height_inc = (node->left == NULL);
528 new_node->parent = node;
530 /* Update branch_size fields of the parent nodes. */
534 for (p = node; p != NULL; p = p->parent)
539 if (height_inc && node->parent != NULL)
540 rebalance (list, node, 1, node->parent);
543 /* Add node to the hash table.
544 Note that this is only possible _after_ the node has been added to the
545 tree structure, because add_to_bucket() uses node_position(). */
546 add_to_bucket (list, new_node);
547 hash_resize_after_add (list);
553 static gl_list_node_t
554 gl_tree_add_after (gl_list_t list, gl_list_node_t node, const void *elt)
556 /* Create new node. */
557 gl_list_node_t new_node =
558 (struct gl_list_node_impl *) xmalloc (sizeof (struct gl_list_node_impl));
561 new_node->left = NULL;
562 new_node->right = NULL;
563 new_node->balance = 0;
564 new_node->branch_size = 1;
565 new_node->value = elt;
567 new_node->h.hashcode =
568 (list->base.hashcode_fn != NULL
569 ? list->base.hashcode_fn (new_node->value)
570 : (size_t)(uintptr_t) new_node->value);
573 /* Add it to the tree. */
574 if (node->right == NULL)
576 node->right = new_node;
578 height_inc = (node->left == NULL);
582 for (node = node->right; node->left != NULL; )
584 node->left = new_node;
586 height_inc = (node->right == NULL);
588 new_node->parent = node;
590 /* Update branch_size fields of the parent nodes. */
594 for (p = node; p != NULL; p = p->parent)
599 if (height_inc && node->parent != NULL)
600 rebalance (list, node, 1, node->parent);
603 /* Add node to the hash table.
604 Note that this is only possible _after_ the node has been added to the
605 tree structure, because add_to_bucket() uses node_position(). */
606 add_to_bucket (list, new_node);
607 hash_resize_after_add (list);
614 gl_tree_remove_node (gl_list_t list, gl_list_node_t node)
616 gl_list_node_t parent;
619 /* Remove node from the hash table.
620 Note that this is only possible _before_ the node is removed from the
621 tree structure, because remove_from_bucket() uses node_position(). */
622 remove_from_bucket (list, node);
625 parent = node->parent;
627 if (node->left == NULL)
629 /* Replace node with node->right. */
630 gl_list_node_t child = node->right;
633 child->parent = parent;
638 if (parent->left == node)
639 parent->left = child;
640 else /* parent->right == node */
641 parent->right = child;
643 /* Update branch_size fields of the parent nodes. */
647 for (p = parent; p != NULL; p = p->parent)
651 rebalance (list, child, -1, parent);
654 else if (node->right == NULL)
656 /* It is not absolutely necessary to treat this case. But the more
657 general case below is more complicated, hence slower. */
658 /* Replace node with node->left. */
659 gl_list_node_t child = node->left;
661 child->parent = parent;
666 if (parent->left == node)
667 parent->left = child;
668 else /* parent->right == node */
669 parent->right = child;
671 /* Update branch_size fields of the parent nodes. */
675 for (p = parent; p != NULL; p = p->parent)
679 rebalance (list, child, -1, parent);
684 /* Replace node with the rightmost element of the node->left subtree. */
685 gl_list_node_t subst;
686 gl_list_node_t subst_parent;
687 gl_list_node_t child;
689 for (subst = node->left; subst->right != NULL; )
690 subst = subst->right;
692 subst_parent = subst->parent;
696 /* The case subst_parent == node is special: If we do nothing special,
697 we get confusion about node->left, subst->left and child->parent.
699 <==> The 'for' loop above terminated immediately.
700 <==> subst == subst_parent->left
701 [otherwise subst == subst_parent->right]
702 In this case, we would need to first set
703 child->parent = node; node->left = child;
704 and later - when we copy subst into node's position - again
705 child->parent = subst; subst->left = child;
706 Altogether a no-op. */
707 if (subst_parent != node)
710 child->parent = subst_parent;
711 subst_parent->right = child;
714 /* Update branch_size fields of the parent nodes. */
718 for (p = subst_parent; p != NULL; p = p->parent)
722 /* Copy subst into node's position.
723 (This is safer than to copy subst's value into node, keep node in
724 place, and free subst.) */
725 if (subst_parent != node)
727 subst->left = node->left;
728 subst->left->parent = subst;
730 subst->right = node->right;
731 subst->right->parent = subst;
732 subst->balance = node->balance;
733 subst->branch_size = node->branch_size;
734 subst->parent = parent;
737 else if (parent->left == node)
738 parent->left = subst;
739 else /* parent->right == node */
740 parent->right = subst;
742 /* Rebalancing starts at child's parent, that is subst_parent -
743 except when subst_parent == node. In this case, we need to use
744 its replacement, subst. */
745 rebalance (list, child, -1, subst_parent != node ? subst_parent : subst);