Allow phone_alloc to not publish the capability
[helenos.git] / kernel / generic / src / adt / avl.c
blob75988d02c02b65c41505cb352ae7427a8ed625b3
1 /*
2 * Copyright (c) 2007 Vojtech Mencl
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /** @addtogroup genericadt
30 * @{
33 /**
34 * @file
35 * @brief AVL tree implementation.
37 * This file implements AVL tree type and operations.
39 * Implemented AVL tree has the following properties:
40 * @li It is a binary search tree with non-unique keys.
41 * @li Difference of heights of the left and the right subtree of every node is
42 * one at maximum.
44 * Every node has a pointer to its parent which allows insertion of multiple
45 * identical keys into the tree.
47 * Be careful when using this tree because of the base atribute which is added
48 * to every inserted node key. There is no rule in which order nodes with the
49 * same key are visited.
52 #include <adt/avl.h>
53 #include <assert.h>
55 #define LEFT 0
56 #define RIGHT 1
58 /** Search for the first occurence of the given key in an AVL tree.
60 * @param t AVL tree.
61 * @param key Key to be searched.
63 * @return Pointer to a node or NULL if there is no such key.
65 avltree_node_t *avltree_search(avltree_t *t, avltree_key_t key)
67 avltree_node_t *p;
70 * Iteratively descend to the leaf that can contain the searched key.
72 p = t->root;
73 while (p != NULL) {
74 if (p->key > key)
75 p = p->lft;
76 else if (p->key < key)
77 p = p->rgt;
78 else
79 return p;
81 return NULL;
85 /** Find the node with the smallest key in an AVL tree.
87 * @param t AVL tree.
89 * @return Pointer to a node or NULL if there is no node in the tree.
91 avltree_node_t *avltree_find_min(avltree_t *t)
93 avltree_node_t *p = t->root;
96 * Check whether the tree is empty.
98 if (!p)
99 return NULL;
102 * Iteratively descend to the leftmost leaf in the tree.
104 while (p->lft != NULL)
105 p = p->lft;
107 return p;
110 #define REBALANCE_INSERT_XX(DIR1, DIR2) \
111 top->DIR1 = par->DIR2; \
112 if (top->DIR1 != NULL) \
113 top->DIR1->par = top; \
114 par->par = top->par; \
115 top->par = par; \
116 par->DIR2 = top; \
117 par->balance = 0; \
118 top->balance = 0; \
119 *dpc = par;
121 #define REBALANCE_INSERT_LL() REBALANCE_INSERT_XX(lft, rgt)
122 #define REBALANCE_INSERT_RR() REBALANCE_INSERT_XX(rgt, lft)
124 #define REBALANCE_INSERT_XY(DIR1, DIR2, SGN) \
125 gpa = par->DIR2; \
126 par->DIR2 = gpa->DIR1; \
127 if (gpa->DIR1 != NULL) \
128 gpa->DIR1->par = par; \
129 gpa->DIR1 = par; \
130 par->par = gpa; \
131 top->DIR1 = gpa->DIR2; \
132 if (gpa->DIR2 != NULL) \
133 gpa->DIR2->par = top; \
134 gpa->DIR2 = top; \
135 gpa->par = top->par; \
136 top->par = gpa; \
138 if (gpa->balance == -1 * SGN) { \
139 par->balance = 0; \
140 top->balance = 1 * SGN; \
141 } else if (gpa->balance == 0) { \
142 par->balance = 0; \
143 top->balance = 0; \
144 } else { \
145 par->balance = -1 * SGN; \
146 top->balance = 0; \
148 gpa->balance = 0; \
149 *dpc = gpa;
151 #define REBALANCE_INSERT_LR() REBALANCE_INSERT_XY(lft, rgt, 1)
152 #define REBALANCE_INSERT_RL() REBALANCE_INSERT_XY(rgt, lft, -1)
154 /** Insert new node into AVL tree.
156 * @param t AVL tree.
157 * @param newnode New node to be inserted.
159 void avltree_insert(avltree_t *t, avltree_node_t *newnode)
161 avltree_node_t *par;
162 avltree_node_t *gpa;
163 avltree_node_t *top;
164 avltree_node_t **dpc;
165 avltree_key_t key;
167 assert(t);
168 assert(newnode);
171 * Creating absolute key.
173 key = newnode->key + t->base;
176 * Iteratively descend to the leaf that can contain the new node.
177 * Last node with non-zero balance in the way to leaf is stored as top -
178 * it is a place of possible inbalance.
180 dpc = &t->root;
181 gpa = NULL;
182 top = t->root;
183 while ((par = (*dpc)) != NULL) {
184 if (par->balance != 0) {
185 top = par;
187 gpa = par;
188 dpc = par->key > key ? &par->lft: &par->rgt;
192 * Initialize the new node.
194 newnode->key = key;
195 newnode->lft = NULL;
196 newnode->rgt = NULL;
197 newnode->par = gpa;
198 newnode->balance = 0;
201 * Insert first node into the empty tree.
203 if (t->root == NULL) {
204 *dpc = newnode;
205 return;
209 * Insert the new node into the previously found leaf position.
211 *dpc = newnode;
214 * If the tree contains one node - end.
216 if (top == NULL)
217 return;
220 * Store pointer of top's father which points to the node with
221 * potentially broken balance (top).
223 if (top->par == NULL) {
224 dpc = &t->root;
225 } else {
226 if (top->par->lft == top)
227 dpc = &top->par->lft;
228 else
229 dpc = &top->par->rgt;
233 * Repair all balances on the way from top node to the newly inserted
234 * node.
236 par = top;
237 while (par != newnode) {
238 if (par->key > key) {
239 par->balance--;
240 par = par->lft;
241 } else {
242 par->balance++;
243 par = par->rgt;
248 * To balance the tree, we must check and balance top node.
250 if (top->balance == -2) {
251 par = top->lft;
252 if (par->balance == -1) {
254 * LL rotation.
256 REBALANCE_INSERT_LL();
257 } else {
259 * LR rotation.
261 assert(par->balance == 1);
263 REBALANCE_INSERT_LR();
265 } else if (top->balance == 2) {
266 par = top->rgt;
267 if (par->balance == 1) {
269 * RR rotation.
271 REBALANCE_INSERT_RR();
272 } else {
274 * RL rotation.
276 assert(par->balance == -1);
278 REBALANCE_INSERT_RL();
280 } else {
282 * Balance is not broken, insertion is finised.
284 return;
289 /** Repair the tree after reparenting node u.
291 * If node u has no parent, mark it as the root of the whole tree. Otherwise
292 * node v represents stale address of one of the children of node u's parent.
293 * Replace v with w as node u parent's child (for most uses, u and w will be the
294 * same).
296 * @param t AVL tree.
297 * @param u Node whose new parent has a stale child pointer.
298 * @param v Stale child of node u's new parent.
299 * @param w New child of node u's new parent.
300 * @param dir If not NULL, address of the variable where to store information
301 * about whether w replaced v in the left or the right subtree of
302 * u's new parent.
303 * @param ro Read only operation; do not modify any tree pointers. This is
304 * useful for tracking direction via the dir pointer.
306 * @return Zero if w became the new root of the tree, otherwise return
307 * non-zero.
309 static int
310 repair(avltree_t *t, avltree_node_t *u, avltree_node_t *v, avltree_node_t *w,
311 int *dir, int ro)
313 if (u->par == NULL) {
314 if (!ro)
315 t->root = w;
316 return 0;
317 } else {
318 if (u->par->lft == v) {
319 if (!ro)
320 u->par->lft = w;
321 if (dir)
322 *dir = LEFT;
323 } else {
324 assert(u->par->rgt == v);
325 if (!ro)
326 u->par->rgt = w;
327 if (dir)
328 *dir = RIGHT;
331 return 1;
334 #define REBALANCE_DELETE(DIR1, DIR2, SIGN) \
335 if (cur->balance == -1 * SIGN) { \
336 par->balance = 0; \
337 gpa->balance = 1 * SIGN; \
338 if (gpa->DIR1) \
339 gpa->DIR1->par = gpa; \
340 par->DIR2->par = par; \
341 } else if (cur->balance == 0) { \
342 par->balance = 0; \
343 gpa->balance = 0; \
344 if (gpa->DIR1) \
345 gpa->DIR1->par = gpa; \
346 if (par->DIR2) \
347 par->DIR2->par = par; \
348 } else { \
349 par->balance = -1 * SIGN; \
350 gpa->balance = 0; \
351 if (par->DIR2) \
352 par->DIR2->par = par; \
353 gpa->DIR1->par = gpa; \
355 cur->balance = 0;
357 #define REBALANCE_DELETE_LR() REBALANCE_DELETE(lft, rgt, 1)
358 #define REBALANCE_DELETE_RL() REBALANCE_DELETE(rgt, lft, -1)
360 /** Delete a node from the AVL tree.
362 * Because multiple identical keys are allowed, the parent pointers are
363 * essential during deletion.
365 * @param t AVL tree structure.
366 * @param node Address of the node which will be deleted.
368 void avltree_delete(avltree_t *t, avltree_node_t *node)
370 avltree_node_t *cur;
371 avltree_node_t *par;
372 avltree_node_t *gpa;
373 int dir;
375 assert(t);
376 assert(node);
378 if (node->lft == NULL) {
379 if (node->rgt) {
381 * Replace the node with its only right son.
383 * Balance of the right son will be repaired in the
384 * balancing cycle.
386 cur = node->rgt;
387 cur->par = node->par;
388 gpa = cur;
389 dir = RIGHT;
390 cur->balance = node->balance;
391 } else {
392 if (node->par == NULL) {
394 * The tree has only one node - it will become
395 * an empty tree and the balancing can end.
397 t->root = NULL;
398 return;
401 * The node has no child, it will be deleted with no
402 * substitution.
404 gpa = node->par;
405 cur = NULL;
406 dir = (gpa->lft == node) ? LEFT: RIGHT;
408 } else {
410 * The node has the left son. Find a node with the smallest key
411 * in the left subtree and replace the deleted node with that
412 * node.
414 cur = node->lft;
415 while (cur->rgt != NULL)
416 cur = cur->rgt;
418 if (cur != node->lft) {
420 * The rightmost node of the deleted node's left subtree
421 * was found. Replace the deleted node with this node.
422 * Cutting off of the found node has two cases that
423 * depend on its left son.
425 if (cur->lft) {
427 * The found node has a left son.
429 gpa = cur->lft;
430 gpa->par = cur->par;
431 dir = LEFT;
432 gpa->balance = cur->balance;
433 } else {
434 dir = RIGHT;
435 gpa = cur->par;
437 cur->par->rgt = cur->lft;
438 cur->lft = node->lft;
439 cur->lft->par = cur;
440 } else {
442 * The left son of the node hasn't got a right son. The
443 * left son will take the deleted node's place.
445 dir = LEFT;
446 gpa = cur;
448 if (node->rgt)
449 node->rgt->par = cur;
450 cur->rgt = node->rgt;
451 cur->balance = node->balance;
452 cur->par = node->par;
456 * Repair the parent node's pointer which pointed previously to the
457 * deleted node.
459 (void) repair(t, node, node, cur, NULL, false);
462 * Repair cycle which repairs balances of nodes on the way from from the
463 * cut-off node up to the root.
465 while (true) {
466 if (dir == LEFT) {
468 * Deletion was made in the left subtree.
470 gpa->balance++;
471 if (gpa->balance == 1) {
473 * Stop balancing, the tree is balanced.
475 break;
476 } else if (gpa->balance == 2) {
478 * Bad balance, heights of left and right
479 * subtrees differ more than by one.
481 par = gpa->rgt;
483 if (par->balance == -1) {
485 * RL rotation.
488 cur = par->lft;
489 par->lft = cur->rgt;
490 cur->rgt = par;
491 gpa->rgt = cur->lft;
492 cur->lft = gpa;
495 * Repair balances and paternity of
496 * children, depending on the balance
497 * factor of the grand child (cur).
499 REBALANCE_DELETE_RL();
502 * Repair paternity.
504 cur->par = gpa->par;
505 gpa->par = cur;
506 par->par = cur;
508 if (!repair(t, cur, gpa, cur, &dir,
509 false))
510 break;
511 gpa = cur->par;
512 } else {
514 * RR rotation.
517 gpa->rgt = par->lft;
518 if (par->lft)
519 par->lft->par = gpa;
520 par->lft = gpa;
523 * Repair paternity.
525 par->par = gpa->par;
526 gpa->par = par;
528 if (par->balance == 0) {
530 * The right child of the
531 * balanced node is balanced,
532 * after RR rotation is done,
533 * the whole tree will be
534 * balanced.
536 par->balance = -1;
537 gpa->balance = 1;
539 (void) repair(t, par, gpa, par,
540 NULL, false);
541 break;
542 } else {
543 par->balance = 0;
544 gpa->balance = 0;
545 if (!repair(t, par, gpa, par,
546 &dir, false))
547 break;
549 gpa = par->par;
551 } else {
553 * Repair the pointer which pointed to the
554 * balanced node. If it was root then balancing
555 * is finished else continue with the next
556 * iteration (parent node).
558 if (!repair(t, gpa, gpa, NULL, &dir, true))
559 break;
560 gpa = gpa->par;
562 } else {
564 * Deletion was made in the right subtree.
566 gpa->balance--;
567 if (gpa->balance == -1) {
569 * Stop balancing, the tree is balanced.
571 break;
572 } else if (gpa->balance == -2) {
574 * Bad balance, heights of left and right
575 * subtrees differ more than by one.
577 par = gpa->lft;
579 if (par->balance == 1) {
581 * LR rotation.
584 cur = par->rgt;
585 par->rgt = cur->lft;
586 cur->lft = par;
587 gpa->lft = cur->rgt;
588 cur->rgt = gpa;
591 * Repair balances and paternity of
592 * children, depending on the balance
593 * factor of the grand child (cur).
595 REBALANCE_DELETE_LR();
598 * Repair paternity.
600 cur->par = gpa->par;
601 gpa->par = cur;
602 par->par = cur;
604 if (!repair(t, cur, gpa, cur, &dir,
605 false))
606 break;
607 gpa = cur->par;
608 } else {
610 * LL rotation.
613 gpa->lft = par->rgt;
614 if (par->rgt)
615 par->rgt->par = gpa;
616 par->rgt = gpa;
618 * Repair paternity.
620 par->par = gpa->par;
621 gpa->par = par;
623 if (par->balance == 0) {
625 * The left child of the
626 * balanced node is balanced,
627 * after LL rotation is done,
628 * the whole tree will be
629 * balanced.
631 par->balance = 1;
632 gpa->balance = -1;
634 (void) repair(t, par, gpa, par,
635 NULL, false);
636 break;
637 } else {
638 par->balance = 0;
639 gpa->balance = 0;
641 if (!repair(t, par, gpa, par,
642 &dir, false))
643 break;
645 gpa = par->par;
647 } else {
649 * Repair the pointer which pointed to the
650 * balanced node. If it was root then balancing
651 * is finished. Otherwise continue with the next
652 * iteration (parent node).
654 if (!repair(t, gpa, gpa, NULL, &dir, true))
655 break;
656 gpa = gpa->par;
663 /** Delete a node with the smallest key from the AVL tree.
665 * @param t AVL tree structure.
667 bool avltree_delete_min(avltree_t *t)
669 avltree_node_t *node;
672 * Start searching for the smallest key in the tree starting in the root
673 * node and continue in cycle to the leftmost node in the tree (which
674 * must have the smallest key).
677 node = t->root;
678 if (!node)
679 return false;
681 while (node->lft != NULL)
682 node = node->lft;
684 avltree_delete(t, node);
686 return true;
689 /** Walk a subtree of an AVL tree in-order and apply a supplied walker on each
690 * visited node.
692 * @param node Node representing the root of an AVL subtree to be
693 * walked.
694 * @param walker Walker function that will be appliad on each visited
695 * node.
696 * @param arg Argument for the walker.
698 * @return Zero if the walk should stop or non-zero otherwise.
700 static bool _avltree_walk(avltree_node_t *node, avltree_walker_t walker,
701 void *arg)
703 if (node->lft) {
704 if (!_avltree_walk(node->lft, walker, arg))
705 return false;
707 if (!walker(node, arg))
708 return false;
709 if (node->rgt) {
710 if (!_avltree_walk(node->rgt, walker, arg))
711 return false;
713 return true;
716 /** Walk the AVL tree in-order and apply the walker function on each visited
717 * node.
719 * @param t AVL tree to be walked.
720 * @param walker Walker function that will be called on each visited
721 * node.
722 * @param arg Argument for the walker.
724 void avltree_walk(avltree_t *t, avltree_walker_t walker, void *arg)
726 if (t->root)
727 _avltree_walk(t->root, walker, arg);
730 /** @}