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.
4
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.
9
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.
14
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/>. */
17
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
24 the index of node.
25 The index of the elements in the node.right subtree are larger than
26 the index of node.
27 */
28
29 /* Tree node implementation, valid for this file only. */
30 struct NODE_IMPL
31 {
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 */
41 NODE_PAYLOAD_FIELDS
42 };
43 typedef struct NODE_IMPL * NODE_T;
44
45 /* Concrete CONTAINER_IMPL type, valid for this file only. */
46 struct CONTAINER_IMPL
47 {
48 struct CONTAINER_IMPL_BASE base;
49 struct NODE_IMPL *root; /* root node or NULL */
50 size_t count; /* number of nodes */
51 };
52
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. */
58 #define MAXHEIGHT 83
59
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!). */
64 static void
65 rebalance (CONTAINER_T container,
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
66 NODE_T node, int height_diff, NODE_T parent)
67 {
68 for (;;)
69 {
70 NODE_T child;
71 int previous_balance;
72 int balance_diff;
73 NODE_T nodeleft;
74 NODE_T noderight;
75
76 child = node;
77 node = parent;
78
79 previous_balance = node->balance;
80
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);
87 else
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
90 to NULL. */
91 balance_diff = - previous_balance;
92
93 node->balance += balance_diff;
94 if (balance_diff == previous_balance)
95 {
96 /* node->balance is outside the range [-1,1]. Must rotate. */
97 NODE_T *nodep;
98
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;
106 else
107 abort ();
108
109 nodeleft = node->left;
110 noderight = node->right;
111
112 if (balance_diff < 0)
113 {
114 /* node->balance = -2. The subtree is heavier on the left side.
115 Rotate from left to right:
116
117 *
118 / \
119 h+2 h
120 */
121 NODE_T nodeleftright = nodeleft->right;
122 if (nodeleft->balance <= 0)
123 {
124 /*
125 * h+2|h+3
126 / \ / \
127 h+2 h --> / h+1|h+2
128 / \ | / \
129 h+1 h|h+1 h+1 h|h+1 h
130 */
131 node->left = nodeleftright;
132 nodeleft->right = node;
133
134 nodeleft->parent = node->parent;
135 node->parent = nodeleft;
136 if (nodeleftright != NULL)
137 nodeleftright->parent = node;
138
139 nodeleft->balance += 1;
140 node->balance = - nodeleft->balance;
141
142 *nodep = nodeleft;
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
146 h+3 to h+2|h+3. */
147 nodeleft->balance - 1
148 : /* nodeleft's height had been incremented from
149 h+1 to h+2. The subtree's height changes from
150 h+2 to h+2|h+3. */
151 nodeleft->balance);
152 }
153 else
154 {
155 /*
156 * h+2
157 / \ / \
158 h+2 h --> h+1 h+1
159 / \ / \ / \
160 h h+1 h L R h
161 / \
162 L R
163
164 */
165 NODE_T L = nodeleft->right = nodeleftright->left;
166 NODE_T R = node->left = nodeleftright->right;
167 nodeleftright->left = nodeleft;
168 nodeleftright->right = node;
169
170 nodeleftright->parent = node->parent;
171 if (L != NULL)
172 L->parent = nodeleft;
173 if (R != NULL)
174 R->parent = node;
175 nodeleft->parent = nodeleftright;
176 node->parent = nodeleftright;
177
178 nodeleft->balance = (nodeleftright->balance > 0 ? -1 : 0);
179 node->balance = (nodeleftright->balance < 0 ? 1 : 0);
180 nodeleftright->balance = 0;
181
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
186 h+3 to h+2. */
187 -1
188 : /* nodeleft's height had been incremented from
189 h+1 to h+2. The subtree's height changes from
190 h+2 to h+2. */
191 0);
192 }
193 }
194 else
195 {
196 /* node->balance = 2. The subtree is heavier on the right side.
197 Rotate from right to left:
198
199 *
200 / \
201 h h+2
202 */
203 NODE_T noderightleft = noderight->left;
204 if (noderight->balance >= 0)
205 {
206 /*
207 * h+2|h+3
208 / \ / \
209 h h+2 --> h+1|h+2 \
210 / \ / \ |
211 h|h+1 h+1 h h|h+1 h+1
212 */
213 node->right = noderightleft;
214 noderight->left = node;
215
216 noderight->parent = node->parent;
217 node->parent = noderight;
218 if (noderightleft != NULL)
219 noderightleft->parent = node;
220
221 noderight->balance -= 1;
222 node->balance = - noderight->balance;
223
224 *nodep = noderight;
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
228 h+3 to h+2|h+3. */
229 - noderight->balance - 1
230 : /* noderight's height had been incremented from
231 h+1 to h+2. The subtree's height changes from
232 h+2 to h+2|h+3. */
233 - noderight->balance);
234 }
235 else
236 {
237 /*
238 * h+2
239 / \ / \
240 h h+2 --> h+1 h+1
241 / \ / \ / \
242 h+1 h h L R h
243 / \
244 L R
245
246 */
247 NODE_T L = node->right = noderightleft->left;
248 NODE_T R = noderight->left = noderightleft->right;
249 noderightleft->left = node;
250 noderightleft->right = noderight;
251
252 noderightleft->parent = node->parent;
253 if (L != NULL)
254 L->parent = node;
255 if (R != NULL)
256 R->parent = noderight;
257 node->parent = noderightleft;
258 noderight->parent = noderightleft;
259
260 node->balance = (noderightleft->balance > 0 ? -1 : 0);
261 noderight->balance = (noderightleft->balance < 0 ? 1 : 0);
262 noderightleft->balance = 0;
263
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
268 h+3 to h+2. */
269 -1
270 : /* noderight's height had been incremented from
271 h+1 to h+2. The subtree's height changes from
272 h+2 to h+2. */
273 0);
274 }
275 }
276 node = *nodep;
277 }
278 else
279 {
280 /* No rotation needed. Only propagation of the height change to the
281 next higher level. */
282 if (height_diff < 0)
283 height_diff = (previous_balance == 0 ? 0 : -1);
284 else
285 height_diff = (node->balance == 0 ? 0 : 1);
286 }
287
288 if (height_diff == 0)
289 break;
290
291 parent = node->parent;
292 if (parent == NULL)
293 break;
294 }
295 }
296
297 static NODE_T
298 gl_tree_nx_add_first (CONTAINER_T container, NODE_PAYLOAD_PARAMS)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
299 {
300 /* Create new node. */
301 NODE_T new_node =
302 (struct NODE_IMPL *) malloc (sizeof (struct NODE_IMPL));
303
304 if (new_node == NULL)
305 return NULL;
306
307 new_node->left = NULL;
308 new_node->right = NULL;
309 new_node->balance = 0;
310 NODE_PAYLOAD_ASSIGN(new_node)
311
312 /* Add it to the tree. */
313 if (container->root == NULL)
314 {
315 container->root = new_node;
316 new_node->parent = NULL;
317 }
318 else
319 {
320 NODE_T node;
321
322 for (node = container->root; node->left != NULL; )
323 node = node->left;
324
325 node->left = new_node;
326 new_node->parent = node;
327 node->balance--;
328
329 /* Rebalance. */
330 if (node->right == NULL && node->parent != NULL)
331 rebalance (container, node, 1, node->parent);
332 }
333
334 container->count++;
335 return new_node;
336 }
337
338 /* Adds the already allocated NEW_NODE to the tree, right before NODE. */
339 static void
340 gl_tree_add_node_before (CONTAINER_T container, NODE_T node, NODE_T new_node)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
341 {
342 bool height_inc;
343
344 new_node->left = NULL;
345 new_node->right = NULL;
346 new_node->balance = 0;
347
348 /* Add it to the tree. */
349 if (node->left == NULL)
350 {
351 node->left = new_node;
352 node->balance--;
353 height_inc = (node->right == NULL);
354 }
355 else
356 {
357 for (node = node->left; node->right != NULL; )
358 node = node->right;
359 node->right = new_node;
360 node->balance++;
361 height_inc = (node->left == NULL);
362 }
363 new_node->parent = node;
364
365 /* Rebalance. */
366 if (height_inc && node->parent != NULL)
367 rebalance (container, node, 1, node->parent);
368
369 container->count++;
370 }
371
372 static NODE_T
373 gl_tree_nx_add_before (CONTAINER_T container, NODE_T node, NODE_PAYLOAD_PARAMS)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
374 {
375 /* Create new node. */
376 NODE_T new_node =
377 (struct NODE_IMPL *) malloc (sizeof (struct NODE_IMPL));
378
379 if (new_node == NULL)
380 return NULL;
381
382 NODE_PAYLOAD_ASSIGN(new_node)
383
384 gl_tree_add_node_before (container, node, new_node);
385 return new_node;
386 }
387
388 /* Adds the already allocated NEW_NODE to the tree, right after NODE. */
389 static void
390 gl_tree_add_node_after (CONTAINER_T container, NODE_T node, NODE_T new_node)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
391 {
392 bool height_inc;
393
394 new_node->left = NULL;
395 new_node->right = NULL;
396 new_node->balance = 0;
397
398 /* Add it to the tree. */
399 if (node->right == NULL)
400 {
401 node->right = new_node;
402 node->balance++;
403 height_inc = (node->left == NULL);
404 }
405 else
406 {
407 for (node = node->right; node->left != NULL; )
408 node = node->left;
409 node->left = new_node;
410 node->balance--;
411 height_inc = (node->right == NULL);
412 }
413 new_node->parent = node;
414
415 /* Rebalance. */
416 if (height_inc && node->parent != NULL)
417 rebalance (container, node, 1, node->parent);
418
419 container->count++;
420 }
421
422 static NODE_T
423 gl_tree_nx_add_after (CONTAINER_T container, NODE_T node, NODE_PAYLOAD_PARAMS)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
424 {
425 /* Create new node. */
426 NODE_T new_node =
427 (struct NODE_IMPL *) malloc (sizeof (struct NODE_IMPL));
428
429 if (new_node == NULL)
430 return NULL;
431
432 NODE_PAYLOAD_ASSIGN(new_node)
433
434 gl_tree_add_node_after (container, node, new_node);
435 return new_node;
436 }
437
438 static void
439 gl_tree_remove_node_no_free (CONTAINER_T container, NODE_T node)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
440 {
441 NODE_T parent = node->parent;
442
443 if (node->left == NULL)
444 {
445 /* Replace node with node->right. */
446 NODE_T child = node->right;
447
448 if (child != NULL)
449 child->parent = parent;
450 if (parent == NULL)
451 container->root = child;
452 else
453 {
454 if (parent->left == node)
455 parent->left = child;
456 else /* parent->right == node */
457 parent->right = child;
458
459 rebalance (container, child, -1, parent);
460 }
461 }
462 else if (node->right == NULL)
463 {
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;
468
469 child->parent = parent;
470 if (parent == NULL)
471 container->root = child;
472 else
473 {
474 if (parent->left == node)
475 parent->left = child;
476 else /* parent->right == node */
477 parent->right = child;
478
479 rebalance (container, child, -1, parent);
480 }
481 }
482 else
483 {
484 /* Replace node with the rightmost element of the node->left subtree. */
485 NODE_T subst;
486 NODE_T subst_parent;
487 NODE_T child;
488
489 for (subst = node->left; subst->right != NULL; )
490 subst = subst->right;
491
492 subst_parent = subst->parent;
493
494 child = subst->left;
495
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.
498 subst_parent == node
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)
508 {
509 if (child != NULL)
510 child->parent = subst_parent;
511 subst_parent->right = child;
512 }
513
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)
518 {
519 subst->left = node->left;
520 subst->left->parent = subst;
521 }
522 subst->right = node->right;
523 subst->right->parent = subst;
524 subst->balance = node->balance;
525 subst->parent = parent;
526 if (parent == NULL)
527 container->root = subst;
528 else if (parent->left == node)
529 parent->left = subst;
530 else /* parent->right == node */
531 parent->right = subst;
532
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);
537 }
538
539 container->count--;
540 }
541
542 static bool
543 gl_tree_remove_node (CONTAINER_T container, NODE_T node)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
544 {
545 gl_tree_remove_node_no_free (container, node);
546 NODE_PAYLOAD_DISPOSE (container, node)
547 free (node);
548 return true;
549 }
550
551 /* For debugging. */
552 static unsigned int
553 check_invariants (NODE_T node, NODE_T parent, size_t *counterp)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
554 {
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;
560
561 if (!(node->parent == parent))
562 abort ();
563 if (!(balance >= -1 && balance <= 1))
564 abort ();
565 if (!(node->balance == balance))
566 abort ();
567
568 (*counterp)++;
569
570 return 1 + (left_height > right_height ? left_height : right_height);
571 }