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. */
31 gl_list_node_t node = XMALLOC (struct gl_list_node_impl);
35 node->left = create_subtree_with_contents (half1, contents);
36 node->left->parent = node;
41 node->value = contents[half1];
45 node->right = create_subtree_with_contents (half2, contents + half1 + 1);
46 node->right->parent = node;
51 /* balance is 0, except when count is a power of two and > 1.
52 Reason: half1 <= half2 <= half1 + 1, and the two branches can have
53 different heights only if half1 = 2^h - 1 and half2 = 2^h; in this
54 case, count = half1 + half2 + 1 = 2^(h+1). */
55 node->balance = (count > 1 && (count & (count - 1)) == 0 ? 1 : 0);
57 node->branch_size = count;
63 gl_tree_create (gl_list_implementation_t implementation,
64 gl_listelement_equals_fn equals_fn,
65 gl_listelement_hashcode_fn hashcode_fn,
66 bool allow_duplicates,
67 size_t count, const void **contents)
69 struct gl_list_impl *list = XMALLOC (struct gl_list_impl);
71 list->base.vtable = implementation;
72 list->base.equals_fn = equals_fn;
73 list->base.hashcode_fn = hashcode_fn;
74 list->base.allow_duplicates = allow_duplicates;
77 size_t estimate = xsum (count, count / 2); /* 1.5 * count */
80 list->table_size = next_prime (estimate);
81 list->table = XCALLOC (list->table_size, gl_hash_entry_t);
86 list->root = create_subtree_with_contents (count, contents);
87 list->root->parent = NULL;
90 /* Now that the tree is built, node_position() works. Now we can
91 add the nodes to the hash table. */
92 add_nodes_to_buckets (list);
101 /* Ensure the tree is balanced, after an insertion or deletion operation.
102 The height of NODE is incremented by HEIGHT_DIFF (1 or -1).
103 PARENT = NODE->parent. (NODE can also be NULL. But PARENT is non-NULL.)
104 Rotation operations are performed starting at PARENT (not NODE itself!). */
106 rebalance (gl_list_t list,
107 gl_list_node_t node, int height_diff, gl_list_node_t parent)
111 gl_list_node_t child;
112 int previous_balance;
114 gl_list_node_t nodeleft;
115 gl_list_node_t noderight;
120 previous_balance = node->balance;
122 /* The balance of NODE is incremented by BALANCE_DIFF: +1 if the right
123 branch's height has increased by 1 or the left branch's height has
124 decreased by 1, -1 if the right branch's height has decreased by 1 or
125 the left branch's height has increased by 1, 0 if no height change. */
126 if (node->left != NULL || node->right != NULL)
127 balance_diff = (child == node->right ? height_diff : -height_diff);
129 /* Special case where above formula doesn't work, because the caller
130 didn't tell whether node's left or right branch shrunk from height 1
132 balance_diff = - previous_balance;
134 node->balance += balance_diff;
135 if (balance_diff == previous_balance)
137 /* node->balance is outside the range [-1,1]. Must rotate. */
138 gl_list_node_t *nodep;
140 if (node->parent == NULL)
141 /* node == list->root */
143 else if (node->parent->left == node)
144 nodep = &node->parent->left;
145 else if (node->parent->right == node)
146 nodep = &node->parent->right;
150 nodeleft = node->left;
151 noderight = node->right;
153 if (balance_diff < 0)
155 /* node->balance = -2. The subtree is heavier on the left side.
156 Rotate from left to right:
162 gl_list_node_t nodeleftleft = nodeleft->left;
163 gl_list_node_t nodeleftright = nodeleft->right;
164 if (nodeleft->balance <= 0)
171 h+1 h|h+1 h+1 h|h+1 h
173 node->left = nodeleftright;
174 nodeleft->right = node;
176 nodeleft->parent = node->parent;
177 node->parent = nodeleft;
178 if (nodeleftright != NULL)
179 nodeleftright->parent = node;
181 nodeleft->balance += 1;
182 node->balance = - nodeleft->balance;
185 (nodeleftright != NULL ? nodeleftright->branch_size : 0)
186 + 1 + (noderight != NULL ? noderight->branch_size : 0);
187 nodeleft->branch_size =
188 nodeleftleft->branch_size + 1 + node->branch_size;
191 height_diff = (height_diff < 0
192 ? /* noderight's height had been decremented from
193 h+1 to h. The subtree's height changes from
195 nodeleft->balance - 1
196 : /* nodeleft's height had been incremented from
197 h+1 to h+2. The subtree's height changes from
213 gl_list_node_t L = nodeleft->right = nodeleftright->left;
214 gl_list_node_t R = node->left = nodeleftright->right;
215 nodeleftright->left = nodeleft;
216 nodeleftright->right = node;
218 nodeleftright->parent = node->parent;
220 L->parent = nodeleft;
223 nodeleft->parent = nodeleftright;
224 node->parent = nodeleftright;
226 nodeleft->balance = (nodeleftright->balance > 0 ? -1 : 0);
227 node->balance = (nodeleftright->balance < 0 ? 1 : 0);
228 nodeleftright->balance = 0;
230 nodeleft->branch_size =
231 (nodeleft->left != NULL ? nodeleft->left->branch_size : 0)
232 + 1 + (nodeleft->right != NULL ? nodeleft->right->branch_size : 0);
234 (node->left != NULL ? node->left->branch_size : 0)
235 + 1 + (node->right != NULL ? node->right->branch_size : 0);
236 nodeleftright->branch_size =
237 nodeleft->branch_size + 1 + node->branch_size;
239 *nodep = nodeleftright;
240 height_diff = (height_diff < 0
241 ? /* noderight's height had been decremented from
242 h+1 to h. The subtree's height changes from
245 : /* nodeleft's height had been incremented from
246 h+1 to h+2. The subtree's height changes from
253 /* node->balance = 2. The subtree is heavier on the right side.
254 Rotate from right to left:
260 gl_list_node_t noderightleft = noderight->left;
261 gl_list_node_t noderightright = noderight->right;
262 if (noderight->balance >= 0)
269 h|h+1 h+1 h h|h+1 h+1
271 node->right = noderightleft;
272 noderight->left = node;
274 noderight->parent = node->parent;
275 node->parent = noderight;
276 if (noderightleft != NULL)
277 noderightleft->parent = node;
279 noderight->balance -= 1;
280 node->balance = - noderight->balance;
283 (nodeleft != NULL ? nodeleft->branch_size : 0)
284 + 1 + (noderightleft != NULL ? noderightleft->branch_size : 0);
285 noderight->branch_size =
286 node->branch_size + 1 + noderightright->branch_size;
289 height_diff = (height_diff < 0
290 ? /* nodeleft's height had been decremented from
291 h+1 to h. The subtree's height changes from
293 - noderight->balance - 1
294 : /* noderight's height had been incremented from
295 h+1 to h+2. The subtree's height changes from
297 - noderight->balance);
311 gl_list_node_t L = node->right = noderightleft->left;
312 gl_list_node_t R = noderight->left = noderightleft->right;
313 noderightleft->left = node;
314 noderightleft->right = noderight;
316 noderightleft->parent = node->parent;
320 R->parent = noderight;
321 node->parent = noderightleft;
322 noderight->parent = noderightleft;
324 node->balance = (noderightleft->balance > 0 ? -1 : 0);
325 noderight->balance = (noderightleft->balance < 0 ? 1 : 0);
326 noderightleft->balance = 0;
329 (node->left != NULL ? node->left->branch_size : 0)
330 + 1 + (node->right != NULL ? node->right->branch_size : 0);
331 noderight->branch_size =
332 (noderight->left != NULL ? noderight->left->branch_size : 0)
333 + 1 + (noderight->right != NULL ? noderight->right->branch_size : 0);
334 noderightleft->branch_size =
335 node->branch_size + 1 + noderight->branch_size;
337 *nodep = noderightleft;
338 height_diff = (height_diff < 0
339 ? /* nodeleft's height had been decremented from
340 h+1 to h. The subtree's height changes from
343 : /* noderight's height had been incremented from
344 h+1 to h+2. The subtree's height changes from
353 /* No rotation needed. Only propagation of the height change to the
354 next higher level. */
356 height_diff = (previous_balance == 0 ? 0 : -1);
358 height_diff = (node->balance == 0 ? 0 : 1);
361 if (height_diff == 0)
364 parent = node->parent;
370 static gl_list_node_t
371 gl_tree_add_first (gl_list_t list, const void *elt)
373 /* Create new node. */
374 gl_list_node_t new_node = XMALLOC (struct gl_list_node_impl);
376 new_node->left = NULL;
377 new_node->right = NULL;
378 new_node->balance = 0;
379 new_node->branch_size = 1;
380 new_node->value = elt;
382 new_node->h.hashcode =
383 (list->base.hashcode_fn != NULL
384 ? list->base.hashcode_fn (new_node->value)
385 : (size_t)(uintptr_t) new_node->value);
388 /* Add it to the tree. */
389 if (list->root == NULL)
391 list->root = new_node;
392 new_node->parent = NULL;
398 for (node = list->root; node->left != NULL; )
401 node->left = new_node;
402 new_node->parent = node;
405 /* Update branch_size fields of the parent nodes. */
409 for (p = node; p != NULL; p = p->parent)
414 if (node->right == NULL && node->parent != NULL)
415 rebalance (list, node, 1, node->parent);
419 /* Add node to the hash table.
420 Note that this is only possible _after_ the node has been added to the
421 tree structure, because add_to_bucket() uses node_position(). */
422 add_to_bucket (list, new_node);
423 hash_resize_after_add (list);
429 static gl_list_node_t
430 gl_tree_add_last (gl_list_t list, const void *elt)
432 /* Create new node. */
433 gl_list_node_t new_node = XMALLOC (struct gl_list_node_impl);
435 new_node->left = NULL;
436 new_node->right = NULL;
437 new_node->balance = 0;
438 new_node->branch_size = 1;
439 new_node->value = elt;
441 new_node->h.hashcode =
442 (list->base.hashcode_fn != NULL
443 ? list->base.hashcode_fn (new_node->value)
444 : (size_t)(uintptr_t) new_node->value);
447 /* Add it to the tree. */
448 if (list->root == NULL)
450 list->root = new_node;
451 new_node->parent = NULL;
457 for (node = list->root; node->right != NULL; )
460 node->right = new_node;
461 new_node->parent = node;
464 /* Update branch_size fields of the parent nodes. */
468 for (p = node; p != NULL; p = p->parent)
473 if (node->left == NULL && node->parent != NULL)
474 rebalance (list, node, 1, node->parent);
478 /* Add node to the hash table.
479 Note that this is only possible _after_ the node has been added to the
480 tree structure, because add_to_bucket() uses node_position(). */
481 add_to_bucket (list, new_node);
482 hash_resize_after_add (list);
488 static gl_list_node_t
489 gl_tree_add_before (gl_list_t list, gl_list_node_t node, const void *elt)
491 /* Create new node. */
492 gl_list_node_t new_node = XMALLOC (struct gl_list_node_impl);
495 new_node->left = NULL;
496 new_node->right = NULL;
497 new_node->balance = 0;
498 new_node->branch_size = 1;
499 new_node->value = elt;
501 new_node->h.hashcode =
502 (list->base.hashcode_fn != NULL
503 ? list->base.hashcode_fn (new_node->value)
504 : (size_t)(uintptr_t) new_node->value);
507 /* Add it to the tree. */
508 if (node->left == NULL)
510 node->left = new_node;
512 height_inc = (node->right == NULL);
516 for (node = node->left; node->right != NULL; )
518 node->right = new_node;
520 height_inc = (node->left == NULL);
522 new_node->parent = node;
524 /* Update branch_size fields of the parent nodes. */
528 for (p = node; p != NULL; p = p->parent)
533 if (height_inc && node->parent != NULL)
534 rebalance (list, node, 1, node->parent);
537 /* Add node to the hash table.
538 Note that this is only possible _after_ the node has been added to the
539 tree structure, because add_to_bucket() uses node_position(). */
540 add_to_bucket (list, new_node);
541 hash_resize_after_add (list);
547 static gl_list_node_t
548 gl_tree_add_after (gl_list_t list, gl_list_node_t node, const void *elt)
550 /* Create new node. */
551 gl_list_node_t new_node = XMALLOC (struct gl_list_node_impl);
554 new_node->left = NULL;
555 new_node->right = NULL;
556 new_node->balance = 0;
557 new_node->branch_size = 1;
558 new_node->value = elt;
560 new_node->h.hashcode =
561 (list->base.hashcode_fn != NULL
562 ? list->base.hashcode_fn (new_node->value)
563 : (size_t)(uintptr_t) new_node->value);
566 /* Add it to the tree. */
567 if (node->right == NULL)
569 node->right = new_node;
571 height_inc = (node->left == NULL);
575 for (node = node->right; node->left != NULL; )
577 node->left = new_node;
579 height_inc = (node->right == NULL);
581 new_node->parent = node;
583 /* Update branch_size fields of the parent nodes. */
587 for (p = node; p != NULL; p = p->parent)
592 if (height_inc && node->parent != NULL)
593 rebalance (list, node, 1, node->parent);
596 /* Add node to the hash table.
597 Note that this is only possible _after_ the node has been added to the
598 tree structure, because add_to_bucket() uses node_position(). */
599 add_to_bucket (list, new_node);
600 hash_resize_after_add (list);
607 gl_tree_remove_node (gl_list_t list, gl_list_node_t node)
609 gl_list_node_t parent;
612 /* Remove node from the hash table.
613 Note that this is only possible _before_ the node is removed from the
614 tree structure, because remove_from_bucket() uses node_position(). */
615 remove_from_bucket (list, node);
618 parent = node->parent;
620 if (node->left == NULL)
622 /* Replace node with node->right. */
623 gl_list_node_t child = node->right;
626 child->parent = parent;
631 if (parent->left == node)
632 parent->left = child;
633 else /* parent->right == node */
634 parent->right = child;
636 /* Update branch_size fields of the parent nodes. */
640 for (p = parent; p != NULL; p = p->parent)
644 rebalance (list, child, -1, parent);
647 else if (node->right == NULL)
649 /* It is not absolutely necessary to treat this case. But the more
650 general case below is more complicated, hence slower. */
651 /* Replace node with node->left. */
652 gl_list_node_t child = node->left;
654 child->parent = parent;
659 if (parent->left == node)
660 parent->left = child;
661 else /* parent->right == node */
662 parent->right = child;
664 /* Update branch_size fields of the parent nodes. */
668 for (p = parent; p != NULL; p = p->parent)
672 rebalance (list, child, -1, parent);
677 /* Replace node with the rightmost element of the node->left subtree. */
678 gl_list_node_t subst;
679 gl_list_node_t subst_parent;
680 gl_list_node_t child;
682 for (subst = node->left; subst->right != NULL; )
683 subst = subst->right;
685 subst_parent = subst->parent;
689 /* The case subst_parent == node is special: If we do nothing special,
690 we get confusion about node->left, subst->left and child->parent.
692 <==> The 'for' loop above terminated immediately.
693 <==> subst == subst_parent->left
694 [otherwise subst == subst_parent->right]
695 In this case, we would need to first set
696 child->parent = node; node->left = child;
697 and later - when we copy subst into node's position - again
698 child->parent = subst; subst->left = child;
699 Altogether a no-op. */
700 if (subst_parent != node)
703 child->parent = subst_parent;
704 subst_parent->right = child;
707 /* Update branch_size fields of the parent nodes. */
711 for (p = subst_parent; p != NULL; p = p->parent)
715 /* Copy subst into node's position.
716 (This is safer than to copy subst's value into node, keep node in
717 place, and free subst.) */
718 if (subst_parent != node)
720 subst->left = node->left;
721 subst->left->parent = subst;
723 subst->right = node->right;
724 subst->right->parent = subst;
725 subst->balance = node->balance;
726 subst->branch_size = node->branch_size;
727 subst->parent = parent;
730 else if (parent->left == node)
731 parent->left = subst;
732 else /* parent->right == node */
733 parent->right = subst;
735 /* Rebalancing starts at child's parent, that is subst_parent -
736 except when subst_parent == node. In this case, we need to use
737 its replacement, subst. */
738 rebalance (list, child, -1, subst_parent != node ? subst_parent : subst);