1 /* Ordered {set,map} data type implemented by a binary tree.
2 Copyright (C) 2006-2007, 2009-2024 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2006.
5 This file is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation; either version 2.1 of the
8 License, or (at your option) any later version.
10 This file 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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser 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
);