1 /* Ordered {set,map} data type implemented by a binary tree.
2 Copyright (C) 2006-2007, 2009-2021 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 3 of the License, or
8 (at your option) any later version.
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, see <https://www.gnu.org/licenses/>. */
18 /* An AVL tree is a binary tree where
19 1. The height of each node is calculated as
20 heightof(node) = 1 + max (heightof(node.left), heightof(node.right)).
21 2. The heights of the subtrees of each node differ by at most 1:
22 | heightof(right) - heightof(left) | <= 1.
23 3. The index of the elements in the node.left subtree are smaller than
25 The index of the elements in the node.right subtree are larger than
29 /* Tree node implementation, valid for this file only. */
32 struct NODE_IMPL *left; /* left branch, or NULL */
33 struct NODE_IMPL *right; /* right branch, or NULL */
34 /* Parent pointer, or NULL. The parent pointer is not needed for most
35 operations. It is needed so that a NODE_T can be returned without
36 memory allocation, on which the functions <container>_remove_node,
37 <container>_add_before, <container>_add_after can be implemented. */
38 struct NODE_IMPL *parent;
39 int balance; /* heightof(right) - heightof(left),
40 always = -1 or 0 or 1 */
43 typedef struct NODE_IMPL * NODE_T;
45 /* Concrete CONTAINER_IMPL type, valid for this file only. */
48 struct CONTAINER_IMPL_BASE base;
49 struct NODE_IMPL *root; /* root node or NULL */
50 size_t count; /* number of nodes */
53 /* An AVL tree of height h has at least F_(h+2) - 1 [Fibonacci number] and at
54 most 2^h - 1 elements. So, h <= 84 (because a tree of height h >= 85 would
55 have at least F_87 - 1 elements, and because even on 64-bit machines,
56 sizeof (NODE_IMPL) * (F_87 - 1) > 2^64
57 this would exceed the address space of the machine. */
60 /* Ensures the tree is balanced, after an insertion or deletion operation.
61 The height of NODE is incremented by HEIGHT_DIFF (1 or -1).
62 PARENT = NODE->parent. (NODE can also be NULL. But PARENT is non-NULL.)
63 Rotation operations are performed starting at PARENT (not NODE itself!). */
65 rebalance (CONTAINER_T container,
66 NODE_T node, int height_diff, NODE_T parent)
79 previous_balance = node->balance;
81 /* The balance of NODE is incremented by BALANCE_DIFF: +1 if the right
82 branch's height has increased by 1 or the left branch's height has
83 decreased by 1, -1 if the right branch's height has decreased by 1 or
84 the left branch's height has increased by 1, 0 if no height change. */
85 if (node->left != NULL || node->right != NULL)
86 balance_diff = (child == node->right ? height_diff : -height_diff);
88 /* Special case where above formula doesn't work, because the caller
89 didn't tell whether node's left or right branch shrunk from height 1
91 balance_diff = - previous_balance;
93 node->balance += balance_diff;
94 if (balance_diff == previous_balance)
96 /* node->balance is outside the range [-1,1]. Must rotate. */
99 if (node->parent == NULL)
100 /* node == container->root */
101 nodep = &container->root;
102 else if (node->parent->left == node)
103 nodep = &node->parent->left;
104 else if (node->parent->right == node)
105 nodep = &node->parent->right;
109 nodeleft = node->left;
110 noderight = node->right;
112 if (balance_diff < 0)
114 /* node->balance = -2. The subtree is heavier on the left side.
115 Rotate from left to right:
121 NODE_T nodeleftright = nodeleft->right;
122 if (nodeleft->balance <= 0)
129 h+1 h|h+1 h+1 h|h+1 h
131 node->left = nodeleftright;
132 nodeleft->right = node;
134 nodeleft->parent = node->parent;
135 node->parent = nodeleft;
136 if (nodeleftright != NULL)
137 nodeleftright->parent = node;
139 nodeleft->balance += 1;
140 node->balance = - nodeleft->balance;
143 height_diff = (height_diff < 0
144 ? /* noderight's height had been decremented from
145 h+1 to h. The subtree's height changes from
147 nodeleft->balance - 1
148 : /* nodeleft's height had been incremented from
149 h+1 to h+2. The subtree's height changes from
165 NODE_T L = nodeleft->right = nodeleftright->left;
166 NODE_T R = node->left = nodeleftright->right;
167 nodeleftright->left = nodeleft;
168 nodeleftright->right = node;
170 nodeleftright->parent = node->parent;
172 L->parent = nodeleft;
175 nodeleft->parent = nodeleftright;
176 node->parent = nodeleftright;
178 nodeleft->balance = (nodeleftright->balance > 0 ? -1 : 0);
179 node->balance = (nodeleftright->balance < 0 ? 1 : 0);
180 nodeleftright->balance = 0;
182 *nodep = nodeleftright;
183 height_diff = (height_diff < 0
184 ? /* noderight's height had been decremented from
185 h+1 to h. The subtree's height changes from
188 : /* nodeleft's height had been incremented from
189 h+1 to h+2. The subtree's height changes from
196 /* node->balance = 2. The subtree is heavier on the right side.
197 Rotate from right to left:
203 NODE_T noderightleft = noderight->left;
204 if (noderight->balance >= 0)
211 h|h+1 h+1 h h|h+1 h+1
213 node->right = noderightleft;
214 noderight->left = node;
216 noderight->parent = node->parent;
217 node->parent = noderight;
218 if (noderightleft != NULL)
219 noderightleft->parent = node;
221 noderight->balance -= 1;
222 node->balance = - noderight->balance;
225 height_diff = (height_diff < 0
226 ? /* nodeleft's height had been decremented from
227 h+1 to h. The subtree's height changes from
229 - noderight->balance - 1
230 : /* noderight's height had been incremented from
231 h+1 to h+2. The subtree's height changes from
233 - noderight->balance);
247 NODE_T L = node->right = noderightleft->left;
248 NODE_T R = noderight->left = noderightleft->right;
249 noderightleft->left = node;
250 noderightleft->right = noderight;
252 noderightleft->parent = node->parent;
256 R->parent = noderight;
257 node->parent = noderightleft;
258 noderight->parent = noderightleft;
260 node->balance = (noderightleft->balance > 0 ? -1 : 0);
261 noderight->balance = (noderightleft->balance < 0 ? 1 : 0);
262 noderightleft->balance = 0;
264 *nodep = noderightleft;
265 height_diff = (height_diff < 0
266 ? /* nodeleft's height had been decremented from
267 h+1 to h. The subtree's height changes from
270 : /* noderight's height had been incremented from
271 h+1 to h+2. The subtree's height changes from
280 /* No rotation needed. Only propagation of the height change to the
281 next higher level. */
283 height_diff = (previous_balance == 0 ? 0 : -1);
285 height_diff = (node->balance == 0 ? 0 : 1);
288 if (height_diff == 0)
291 parent = node->parent;
298 gl_tree_nx_add_first (CONTAINER_T container, NODE_PAYLOAD_PARAMS)
300 /* Create new node. */
302 (struct NODE_IMPL *) malloc (sizeof (struct NODE_IMPL));
304 if (new_node == NULL)
307 new_node->left = NULL;
308 new_node->right = NULL;
309 new_node->balance = 0;
310 NODE_PAYLOAD_ASSIGN(new_node)
312 /* Add it to the tree. */
313 if (container->root == NULL)
315 container->root = new_node;
316 new_node->parent = NULL;
322 for (node = container->root; node->left != NULL; )
325 node->left = new_node;
326 new_node->parent = node;
330 if (node->right == NULL && node->parent != NULL)
331 rebalance (container, node, 1, node->parent);
338 /* Adds the already allocated NEW_NODE to the tree, right before NODE. */
340 gl_tree_add_node_before (CONTAINER_T container, NODE_T node, NODE_T new_node)
344 new_node->left = NULL;
345 new_node->right = NULL;
346 new_node->balance = 0;
348 /* Add it to the tree. */
349 if (node->left == NULL)
351 node->left = new_node;
353 height_inc = (node->right == NULL);
357 for (node = node->left; node->right != NULL; )
359 node->right = new_node;
361 height_inc = (node->left == NULL);
363 new_node->parent = node;
366 if (height_inc && node->parent != NULL)
367 rebalance (container, node, 1, node->parent);
373 gl_tree_nx_add_before (CONTAINER_T container, NODE_T node, NODE_PAYLOAD_PARAMS)
375 /* Create new node. */
377 (struct NODE_IMPL *) malloc (sizeof (struct NODE_IMPL));
379 if (new_node == NULL)
382 NODE_PAYLOAD_ASSIGN(new_node)
384 gl_tree_add_node_before (container, node, new_node);
388 /* Adds the already allocated NEW_NODE to the tree, right after NODE. */
390 gl_tree_add_node_after (CONTAINER_T container, NODE_T node, NODE_T new_node)
394 new_node->left = NULL;
395 new_node->right = NULL;
396 new_node->balance = 0;
398 /* Add it to the tree. */
399 if (node->right == NULL)
401 node->right = new_node;
403 height_inc = (node->left == NULL);
407 for (node = node->right; node->left != NULL; )
409 node->left = new_node;
411 height_inc = (node->right == NULL);
413 new_node->parent = node;
416 if (height_inc && node->parent != NULL)
417 rebalance (container, node, 1, node->parent);
423 gl_tree_nx_add_after (CONTAINER_T container, NODE_T node, NODE_PAYLOAD_PARAMS)
425 /* Create new node. */
427 (struct NODE_IMPL *) malloc (sizeof (struct NODE_IMPL));
429 if (new_node == NULL)
432 NODE_PAYLOAD_ASSIGN(new_node)
434 gl_tree_add_node_after (container, node, new_node);
439 gl_tree_remove_node_no_free (CONTAINER_T container, NODE_T node)
441 NODE_T parent = node->parent;
443 if (node->left == NULL)
445 /* Replace node with node->right. */
446 NODE_T child = node->right;
449 child->parent = parent;
451 container->root = child;
454 if (parent->left == node)
455 parent->left = child;
456 else /* parent->right == node */
457 parent->right = child;
459 rebalance (container, child, -1, parent);
462 else if (node->right == NULL)
464 /* It is not absolutely necessary to treat this case. But the more
465 general case below is more complicated, hence slower. */
466 /* Replace node with node->left. */
467 NODE_T child = node->left;
469 child->parent = parent;
471 container->root = child;
474 if (parent->left == node)
475 parent->left = child;
476 else /* parent->right == node */
477 parent->right = child;
479 rebalance (container, child, -1, parent);
484 /* Replace node with the rightmost element of the node->left subtree. */
489 for (subst = node->left; subst->right != NULL; )
490 subst = subst->right;
492 subst_parent = subst->parent;
496 /* The case subst_parent == node is special: If we do nothing special,
497 we get confusion about node->left, subst->left and child->parent.
499 <==> The 'for' loop above terminated immediately.
500 <==> subst == subst_parent->left
501 [otherwise subst == subst_parent->right]
502 In this case, we would need to first set
503 child->parent = node; node->left = child;
504 and later - when we copy subst into node's position - again
505 child->parent = subst; subst->left = child;
506 Altogether a no-op. */
507 if (subst_parent != node)
510 child->parent = subst_parent;
511 subst_parent->right = child;
514 /* Copy subst into node's position.
515 (This is safer than to copy subst's value into node, keep node in
516 place, and free subst.) */
517 if (subst_parent != node)
519 subst->left = node->left;
520 subst->left->parent = subst;
522 subst->right = node->right;
523 subst->right->parent = subst;
524 subst->balance = node->balance;
525 subst->parent = parent;
527 container->root = subst;
528 else if (parent->left == node)
529 parent->left = subst;
530 else /* parent->right == node */
531 parent->right = subst;
533 /* Rebalancing starts at child's parent, that is subst_parent -
534 except when subst_parent == node. In this case, we need to use
535 its replacement, subst. */
536 rebalance (container, child, -1, subst_parent != node ? subst_parent : subst);
543 gl_tree_remove_node (CONTAINER_T container, NODE_T node)
545 gl_tree_remove_node_no_free (container, node);
546 NODE_PAYLOAD_DISPOSE (container, node)
553 check_invariants (NODE_T node, NODE_T parent, size_t *counterp)
555 unsigned int left_height =
556 (node->left != NULL ? check_invariants (node->left, node, counterp) : 0);
557 unsigned int right_height =
558 (node->right != NULL ? check_invariants (node->right, node, counterp) : 0);
559 int balance = (int)right_height - (int)left_height;
561 if (!(node->parent == parent))
563 if (!(balance >= -1 && balance <= 1))
565 if (!(node->balance == balance))
570 return 1 + (left_height > right_height ? left_height : right_height);