Subversion Repositories HelenOS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2466 mencl 1
/*
2
 * Copyright (c) 2007 Vojtech Mencl
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 *
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.
16
 *
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.
27
 */
28
 
29
/** @addtogroup genericadt
30
 * @{
31
 */
32
 
33
/**
34
 * @file
35
 * @brief   Fast AVL tree implementation.
36
 *
37
 * This file implements Fast AVL tree type and operations.
38
 *
39
 * Implemented Fast AVL tree has the following properties:
40
 * @li It is binary search tree with non-unique keys.
41
 * @li Difference of heights of left and right subtree of every node is max 1.
42
 *
43
 * Every node has pointer to its parent which allows insertion of multiple identical keys
44
 * into tree. Every FAVL tree has pointer to its node with smallest key that allows
45
 * search and delete of node with smallest key in constant time.
46
 *
47
 * Be careful of using this tree because of base atribute, which is added to every inserted
48
 * node key. There is no rule in which order nodes with the same key are visited.
49
 */
50
 
51
#include <adt/favl.h>
52
#include <debug.h>
53
 
54
 
55
#define AVLTREE_LEFT 0
56
#define AVLTREE_RIGHT 1
57
 
58
 
59
/** Search first occurence of given key in FAVL tree.
60
 *
61
 * @param t FAVL tree.
62
 * @param key Key to be searched.
63
 *
64
 * @return Pointer to node or NULL if there is no such key.
65
 */
66
favltree_node_t *favltree_search(favltree_t *t, uint64_t key)
67
{
68
    favltree_node_t *p;
69
 
70
    /*
71
     * Iteratively descend to the leaf that can contain the searched key.
72
     */
73
    p = t->root;
74
    while (p != NULL) {
75
        if (p->key > key)
76
            p = p->lft;
77
        else if (p->key < key)
78
            p = p->rgt;
79
        else {
80
            return p;
81
        }
82
    }
83
    return NULL;
84
}
85
 
86
 
87
 
88
/** Insert new node into FAVL tree.
89
 *
90
 * @param t FAVL tree.
91
 * @param newnode New node to be inserted.
92
 */
93
void favltree_insert(favltree_t *t, favltree_node_t *newnode)
94
{  
95
    favltree_node_t *par;
96
    favltree_node_t *gpa;
97
    favltree_node_t *top;
98
    favltree_node_t **dpc;
99
    uint64_t key;
100
    bool leftmost;
101
 
102
    ASSERT(t);
103
    ASSERT(newnode);
104
 
105
    /*
106
     * Creating absolute key.
107
     */
108
    key = newnode->key + t->base;
109
 
110
    /*
111
     * Iteratively descend to the leaf that can contain new node.
112
     * Last node with non-zero balance in the way to leaf is stored as top -
113
     * it si place of possible balance fault. Remember if there was any right child
114
     * on the way to leaf.
115
     */
116
    dpc = &t->root;
117
    gpa = NULL;
118
    top = t->root;
119
    leftmost = true;
120
    while ((par = (*dpc)) != NULL) {
121
        if (par->balance != 0) {
122
            top = par;
123
        }
124
        gpa = par;
125
        if (par->key > key) {
126
            dpc = &par->lft;
127
        } else {
128
            dpc = &par->rgt;
129
            leftmost = false;
130
        }
131
    }
132
 
133
    /*
134
     * Initialize new node.
135
     */
136
    newnode->key = key;
137
    newnode->lft = NULL;
138
    newnode->rgt = NULL;
139
    newnode->par = gpa;
140
    newnode->balance = 0;
141
 
142
    /*
143
     * Change pointer to node with minimal key if newnode was smaller then every
144
     * key in tree.
145
     */
146
    if (leftmost) {
147
        t->first = newnode;
148
    }
149
 
150
    /*
151
     * Insert first node into empty tree.
152
     */
153
    if (t->root == NULL) {
154
        *dpc = newnode;
155
        return;
156
    }
157
 
158
    /*
159
     * Insert new node into previously found leaf place.
160
     */
161
    *dpc = newnode;
162
 
163
    /*
164
     * If tree contains one node - end.
165
     */
166
    if (top == NULL) return;
167
 
168
    /*
169
     * Store pointer of top's father which points to the node with potentialy broken
170
     * balance (top).
171
     */
172
    if (top->par == NULL)
173
        dpc = &t->root;
174
    else
175
        if (top->par->lft == top)
176
            dpc = &(top->par->lft);
177
        else
178
            dpc = &(top->par->rgt);
179
 
180
    /*
181
     * Repair all balances on the way from top node to newly inserted node.
182
     */
183
    par = top;
184
    while (par != newnode) {
185
        if (par->key > key) {
186
            par->balance--;
187
            par = par->lft;
188
        } else {
189
            par->balance++;
190
            par = par->rgt;
191
        }
192
    }
193
 
194
    /*
195
     * To balance tree we must check and balance top node.
196
     */
197
    if (top->balance == -2) {
198
        par = top->lft;
199
        if (par->balance == -1) {
200
            /*
201
             * LL rotation.
202
             */
203
            top->lft = par->rgt;
204
            if (top->lft != NULL) top->lft->par = top;
205
            par->par = top->par;
206
            top->par = par;
207
            par->rgt = top;
208
            par->balance = top->balance = 0;
209
            *dpc = par;
210
        } else {
211
            /*
212
             * LR rotation.
213
             */
214
            ASSERT(par->balance == 1);
215
 
216
            gpa = par->rgt;
217
            par->rgt = gpa->lft;
218
            if (gpa->lft != NULL) gpa->lft->par = par;
219
            gpa->lft = par;
220
            par->par = gpa;
221
            top->lft = gpa->rgt;
222
            if (gpa->rgt != NULL) gpa->rgt->par = top;
223
            gpa->rgt = top;
224
            gpa->par = top->par;
225
            top->par = gpa;
226
 
227
            if (gpa->balance == -1) {
228
                par->balance = 0;
229
                top->balance = 1;
230
            } else if (gpa->balance == 0) {
231
                par->balance = top->balance = 0;
232
            } else {
233
                par->balance = -1;
234
                top->balance = 0;
235
            }
236
            gpa->balance = 0;
237
            *dpc = gpa;
238
        }
239
    } else if (top->balance == 2) {
240
        par = top->rgt;
241
        if (par->balance == 1) {
242
            /*
243
             * RR rotation.
244
             */
245
            top->rgt = par->lft;
246
            if (top->rgt != NULL) top->rgt->par = top;
247
            par->par = top->par;
248
            top->par = par;
249
            par->lft = top;
250
            par->balance = top->balance = 0;
251
            *dpc = par;
252
        } else {
253
            /*
254
             * RL rotation.
255
             */
256
            ASSERT(par->balance == -1);
257
 
258
            gpa = par->lft;
259
            par->lft = gpa->rgt;
260
            if (gpa->rgt != NULL) gpa->rgt->par = par;
261
            gpa->rgt = par;
262
            par->par = gpa;
263
            top->rgt = gpa->lft;
264
            if (gpa->lft != NULL) gpa->lft->par = top;
265
            gpa->lft = top;
266
            gpa->par = top->par;
267
            top->par = gpa;
268
 
269
            if (gpa->balance == 1) {
270
                par->balance = 0;
271
                top->balance = -1;
272
            } else if (gpa->balance == 0) {
273
                par->balance = top->balance = 0;
274
            } else {
275
                par->balance = 1;
276
                top->balance = 0;
277
            }
278
            gpa->balance = 0;
279
            *dpc = gpa;
280
        }
281
    } else {
282
        /*
283
         * Balance is not broken, insertion is finised.
284
         */
285
        return;
286
    }
287
 
288
}
289
 
290
/** Delete node from FAVL tree.
291
 *
292
 * Because of allowed multiple identical keys parent pointers are essential
293
 * during deletition.
294
 *
295
 * @param t FAVL tree structure.
296
 * @param node Address of node which will be deleted.
297
 */
298
void favltree_delete(favltree_t *t, favltree_node_t *node)
299
{
300
    favltree_node_t *cur;
301
    favltree_node_t *par;
302
    favltree_node_t *gpa;
303
    uint8_t dir;
304
 
305
    ASSERT(t);
306
    ASSERT(node);
307
 
308
    /*
309
     * If deleted node is node with minimal key then find new minimal key.
310
     */
311
    if (node == t->first) {
312
        if (node->rgt) {
313
            /*
314
             * Deleted node has right child, find minimal key in right child's left
315
             * subtree.
316
             */
317
            cur = node->rgt;
318
            while (cur->lft)
319
                cur = cur->lft;
320
            t->first = cur;
321
        } else if (node->par) {
322
            /*
323
             * Node doesn't have any child but has parent, new minimal key
324
             * has deleted node's parent.
325
             */
326
            t->first = node->par;
327
        } else {
328
            /*
329
             * Deleted node is only node in tree then there will be no minimal key.
330
             */
331
            t->first = NULL;
332
        }
333
    }
334
 
335
    if (node->lft == NULL) {
336
        if (node->rgt) {
337
            /*
338
             * Replace node with its only right son.
339
             *
340
             * Balance of right son will be repaired in balancing cycle.
341
             */
342
            cur = node->rgt;
343
            cur->par = node->par;
344
            gpa = cur;
345
            dir = AVLTREE_RIGHT;
346
            cur->balance = node->balance;
347
        } else {
348
            if (node->par == NULL) {
349
                /*
350
                 * Tree has only one node - it will be empty tree and balancing can end.
351
                 */
352
                t->root = NULL;
353
                return;
354
            }
355
            /*
356
             * Node has no child, will be deleted with no substitution.
357
             */
358
            gpa = node->par;
359
            cur = NULL;
360
            dir = (gpa->lft == node)? AVLTREE_LEFT: AVLTREE_RIGHT;
361
        }
362
    } else {
363
        /*
364
         * Node has left and right son. Find a node with smallest key in left subtree
365
         * and replace deleted node with that node.
366
         */
367
        for (cur = node->lft; cur->rgt != NULL; cur = cur->rgt)
368
            ;
369
 
370
        //cur obsahuje uzel, ktery vlozim misto uzlu node
371
 
372
        if (cur != node->lft) {
373
            /*
374
             * The most right node of deleted node's left subtree was found. Replace
375
             * deleted node with this node. Cutting founded node has two cases in
376
             * dependence on its left son.
377
             */
378
            if (cur->lft) {
379
                /*
380
                 * Founded node has left son.
381
                 */
382
                gpa = cur->lft;
383
                gpa->par = cur->par;
384
                dir = AVLTREE_LEFT;
385
                gpa->balance = cur->balance;
386
            } else {
387
                dir = AVLTREE_RIGHT;
388
                gpa = cur->par;
389
            }
390
            cur->par->rgt = cur->lft;
391
            cur->lft = node->lft;
392
            cur->lft->par = cur;
393
        } else {
394
            /*
395
             * Left son of node hasn't got right son. Left son will take deleted node's place.
396
             */
397
            dir = AVLTREE_LEFT;
398
            gpa = cur;
399
        }
400
        if (node->rgt) node->rgt->par = cur;
401
        cur->rgt = node->rgt;
402
        cur->balance = node->balance;
403
        cur->par = node->par;
404
    }
405
 
406
    /*
407
     * Repair parent nodes pointer which pointed previously to deleted node.
408
     */
409
    if (node->par == NULL) {
410
        t->root = cur;
411
    } else {
412
        if (node->par->lft == node) {
413
            node->par->lft = cur;
414
        } else {
415
            node->par->rgt = cur;
416
        }
417
    }
418
 
419
    /*
420
     * Repair cycle which repairs balances of nodes in way from cutted noded down to root.
421
     */
422
    for(;;) {
423
        if (dir == AVLTREE_LEFT) {
424
            /*
425
             * Deletition was made in left subtree.
426
             */
427
            gpa->balance++;
428
            if (gpa->balance == +1) {
429
                /*
430
                 * Stop balancing, tree is balanced.
431
                 */
432
                break;
433
            } else if (gpa->balance == +2) {
434
                /*
435
                 * Bad balance, heights of left and right subtrees differs more then is allowed.
436
                 */
437
                par = gpa->rgt;
438
 
439
                if (par->balance == -1) {
440
                    /*
441
                     * RL rotation.
442
                     */
443
 
444
                    cur = par->lft;
445
                    par->lft = cur->rgt;
446
                    cur->rgt = par;
447
                    gpa->rgt = cur->lft;
448
                    cur->lft = gpa;
449
 
450
                    /*
451
                     * Repair balances and paternity of childs in dependence on
452
                     * balance factor of grand child (cur).
453
                     */
454
                    if (cur->balance == +1) {
455
                        par->balance = 0;
456
                        gpa->balance = -1;
457
                        if (gpa->rgt) gpa->rgt->par = gpa;
458
                        par->lft->par = par;
459
                    } else if (cur->balance == 0) {
460
                        par->balance = gpa->balance = 0;
461
                        if (gpa->rgt) gpa->rgt->par = gpa;
462
                        if (par->lft) par->lft->par = par;
463
                    } else {
464
                        par->balance = +1;
465
                        gpa->balance = 0;
466
                        if (par->lft) par->lft->par = par;
467
                        gpa->rgt->par = gpa;
468
                    }
469
                    cur->balance = 0;
470
 
471
                    /*
472
                     * Repair paternity.
473
                     */
474
                    cur->par = gpa->par;
475
                    gpa->par = cur;
476
                    par->par = cur;
477
 
478
                    /*
479
                     * Repair pointer which pointed to balanced node. If it was root then balancing
480
                     * is finished else continue in next iteration (parent node).
481
                     */
482
                    if (cur->par == NULL) {
483
                        t->root = cur; 
484
                        break;
485
                    } else
486
                        if (cur->par->lft == gpa) {
487
                            cur->par->lft = cur;
488
                            dir = AVLTREE_LEFT;
489
                        } else {
490
                            cur->par->rgt = cur;
491
                            dir = AVLTREE_RIGHT;
492
                        }
493
                    gpa = cur->par;
494
                } else {
495
                    /*
496
                     * RR rotation.
497
                     */
498
 
499
                    gpa->rgt = par->lft;
500
                    if (par->lft) par->lft->par = gpa;
501
                    par->lft = gpa;
502
 
503
                    /*
504
                     * Repair paternity.
505
                     */
506
                    par->par = gpa->par;
507
                    gpa->par = par;
508
 
509
                    if (par->balance == 0) {
510
                        /*
511
                         * Right child of balanced node is balanced, after RR rotation is done, whole
512
                         * tree will be balanced.
513
                         */
514
                        par->balance = -1;
515
                        gpa->balance = +1;
516
 
517
                        /*
518
                         * Repair pointer which pointed to balanced node and finish balancing.
519
                         */
520
                        if (par->par == NULL) {
521
                            t->root = par; 
522
                        } else
523
                            if (par->par->lft == gpa) {
524
                                par->par->lft = par;
525
                            } else {
526
                                par->par->rgt = par;
527
                            }
528
                        break;
529
                    } else {
530
                        par->balance = gpa->balance = 0;
531
                        /*
532
                         * Repair pointer which pointed to balanced node. If it was root then balancing
533
                         * is finished else continue in next iteration (parent node).
534
                         */
535
                        if (par->par == NULL) {
536
                            t->root = par; 
537
                            break;
538
                        } else {
539
 
540
                            if (par->par->lft == gpa) {
541
                                par->par->lft = par;
542
                                dir = AVLTREE_LEFT;
543
                            } else {
544
                                par->par->rgt = par;
545
                                dir = AVLTREE_RIGHT;
546
                            }
547
                        }
548
                    }
549
                    gpa = par->par;
550
                }
551
            } else {
552
                /*
553
                 * Repair pointer which pointed to balanced node. If it was root then balancing
554
                 * is finished else continue in next iteration (parent node).
555
                 */
556
                if (!gpa->par) break;
557
 
558
                if (gpa->par->lft == gpa) {
559
                    dir = AVLTREE_LEFT;
560
                } else {
561
                    dir = AVLTREE_RIGHT;
562
                }
563
                gpa = gpa->par;
564
            }
565
        } else {
566
            /*
567
             * Deletition was made in right subtree.
568
             */
569
            gpa->balance--;
570
            if (gpa->balance == -1) {
571
                /*
572
                 * Stop balancing, tree is balanced.
573
                 */
574
                break;
575
            } else if (gpa->balance == -2) {
576
                /*
577
                 * Bad balance, heights of left and right subtrees differs more then is allowed.
578
                 */
579
                par = gpa->lft;
580
 
581
                if (par->balance == +1) {
582
                    /*
583
                     * LR rotation.
584
                     */
585
 
586
                    cur = par->rgt;
587
                    par->rgt = cur->lft;
588
                    cur->lft = par;
589
                    gpa->lft = cur->rgt;
590
                    cur->rgt = gpa;
591
 
592
                    /*
593
                     * Repair balances and paternity of childs in dependence on
594
                     * balance factor of grand child (cur).
595
                     */
596
                    if (cur->balance == -1) {
597
                        par->balance = 0;
598
                        gpa->balance = +1;
599
                        if (gpa->lft) gpa->lft->par = gpa;
600
                        par->rgt->par = par;
601
                    } else if (cur->balance == 0) {
602
                        par->balance = gpa->balance = 0;
603
                        if (gpa->lft) gpa->lft->par = gpa;
604
                        if (par->rgt) par->rgt->par = par;
605
                    } else {
606
                        par->balance = -1;
607
                        gpa->balance = 0;
608
                        if (par->rgt) par->rgt->par = par;
609
                        gpa->lft->par = gpa;
610
                    }
611
                    cur->balance = 0;
612
 
613
                    /*
614
                     * Repair paternity.
615
                     */
616
                    cur->par = gpa->par;
617
                    gpa->par = cur;
618
                    par->par = cur;
619
 
620
                    /*
621
                     * Repair pointer which pointed to balanced node. If it was root then balancing
622
                     * is finished else continue in next iteration (parent node).
623
                     */
624
                    if (cur->par == NULL) {
625
                        t->root = cur; 
626
                        break;
627
                    } else
628
                        if (cur->par->lft == gpa) {
629
                            cur->par->lft = cur;
630
                            dir = AVLTREE_LEFT;
631
                        } else {
632
                            cur->par->rgt = cur;
633
                            dir = AVLTREE_RIGHT;
634
                        }
635
                    gpa = cur->par;
636
                } else {
637
                    /*
638
                     * LL rotation.
639
                     */
640
 
641
                    gpa->lft = par->rgt;
642
                    if (par->rgt) par->rgt->par = gpa;
643
                    par->rgt = gpa;
644
                    /*
645
                     * Repair paternity.
646
                     */
647
                    par->par = gpa->par;
648
                    gpa->par = par;
649
 
650
                    if (par->balance == 0) {
651
                        /*
652
                         * Left child of balanced node is balanced, after RR rotation is done, whole
653
                         * tree will be balanced.
654
                         */
655
                        par->balance = +1;
656
                        gpa->balance = -1;
657
 
658
                        /*
659
                         * Repair pointer which pointed to balanced node and finish balancing.
660
                         */
661
                        if (par->par == NULL) {
662
                            t->root = par;
663
                        } else
664
                            if (par->par->lft == gpa) {
665
                                par->par->lft = par;
666
                            } else {
667
                                par->par->rgt = par;
668
                            }
669
                        break;
670
                    } else {
671
                        par->balance = gpa->balance = 0;
672
 
673
                        /*
674
                         * Repair pointer which pointed to balanced node. If it was root then balancing
675
                         * is finished else continue in next iteration (parent node).
676
                         */
677
                        if (par->par == NULL) {
678
                            t->root = par;
679
                            break;
680
                        } else {
681
                            if (par->par->lft == gpa) { //v cyklu jsem ani jednou neskocil - cur nema praveho syna
682
                                par->par->lft = par;
683
                                dir = AVLTREE_LEFT;
684
                            } else {
685
                                par->par->rgt = par;
686
                                dir = AVLTREE_RIGHT;
687
                            }
688
                        }
689
                    }
690
                    gpa = par->par;
691
                }
692
            } else {
693
                /*
694
                 * Repair pointer which pointed to balanced node. If it was root then balancing
695
                 * is finished else continue in next iteration (parent node).
696
                 */
697
                if (!gpa->par) break;
698
 
699
                if (gpa->par->lft == gpa) {
700
                    dir = AVLTREE_LEFT;
701
                } else {
702
                    dir = AVLTREE_RIGHT;
703
                }
704
                gpa = gpa->par;
705
            }
706
        }
707
    }
708
}
709
 
710
 
711
/** Delete node from FAVL tree with the smallest key.
712
 *
713
 * @param t FAVL tree structure.
714
 */
715
bool favltree_delete_min(favltree_t *t)
716
{
717
    /*
718
     * Use favltree_delete function to delete node from tree.
719
     */
720
    favltree_delete(t,t->first);
721
 
722
    return true;
723
}