homedukeAlgorithmen & Datenstrukturen mit Java: Beispielklasse für Verzeichnisse als Rot-Schwarz-Bäume Prof. Dr. Uwe Schmidt FH Wedel

Beispielklasse für Verzeichnisse als Rot-Schwarz-Bäume

weiter

weiter

Map
Schnittstelle wie bei binärem Suchbaum
weiter
   1package ds.interfaces;
   2
   3/** Simple interface for maps
   4 */
   5
   6import java.util.Iterator;
   7
   8import ds.util.Invariant;
   9import ds.util.Function2;
  10
  11import ds.util.K;  // example class for keys
  12import ds.util.V;  // example class for values
  13import ds.util.KV// key value pair
  14
  15public
  16    interface Map
  17    extends Iterable<KV>,
  18            Invariant {
  19
  20    boolean isEmpty();
  21    boolean member(K k);
  22    V       lookup(K k);
  23    int     size();
  24    KV      findMin();
  25    KV      findMax();
  26    Map     insert(K kV v);
  27    Map     remove(K k);
  28    Map     union(Map m2);
  29    Map     difference(Map m2);
  30    Map     unionWith(Function2<V,V,V> opMap m2);
  31    Map     differenceWith(Function2<V,V,V> opMap m2);
  32    Map     copy();
  33
  34    // inherited
  35
  36    // public Iterator<KV> iterator();
  37    // public inv();
  38}
weiter
Map
implementiert als Rot-Schwarz-Baum
ohne Generics
persistente Implementierung
destruktive Implementierung in Kommentar
lesende Funktionen wie bei binären Suchbäumen
mit Methode zum Löschen von Elementen
Invariante ist eine Verschärfung der Invariante für binäre Suchbäume
weiter
   1package ds.persistent.map;
   2
   3/** This is a translation of a Haskell implementation
   4    for red-black trees from
   5    http://matt.might.net/articles/red-black-delete/
   6    The Haskell source can be found under
   7    http://matt.might.net/articles/red-black-delete/code/RedBlackSet.hs
   8  
   9    This Java implementation is a PERSISTENT one and
  10    it supports deletion.
  11*/
  12
  13import ds.interfaces.Map;
  14
  15import ds.util.K;            // example class for keys
  16import ds.util.V;            // example class for values
  17import ds.util.KV;           // key value pair
  18import ds.util.Queue;        // used by iterators
  19import ds.util.Function2;
  20import ds.util.NullIterator;
  21
  22import static ds.util.KV.mkPair;
  23import static ds.util.Boolean.toInt;
  24import static ds.util.Integer.max;
  25import static ds.util.Integer.min;
  26import static ds.util.Undef.undefined;
  27
  28import java.util.Iterator;
  29
  30import static java.lang.Integer.signum;
  31
  32//----------------------------------------
  33
  34public abstract
  35    class RedBlackTree
  36    implements Map {
  37    
  38    /* trc *
  39    static void msg(String s) {
  40        System.out.println(s);
  41    }
  42    
  43    static RedBlackTree trc(String s, RedBlackTree t) {
  44        msg(s + " " + t);
  45        return t;
  46    }
  47    /**/
  48    
  49    //----------------------------------------
  50    // the smart constructors
  51    
  52    // empty tree
  53    public static
  54        RedBlackTree empty() {
  55        return
  56            EMPTY;
  57    }
  58    
  59    // singleton tree
  60    public static
  61        RedBlackTree singleton(K kV v) {
  62         return
  63             empty().insert(kv);
  64    }
  65    
  66    // build search tree from arbitrary sequence (iterator)
  67    public static
  68        RedBlackTree fromIterator(Iterator<KV> elems) {
  69        
  70        RedBlackTree res = empty();
  71        while ( elems.hasNext() ) {
  72            KV p = elems.next();
  73            res = res.insert(p.fstp.snd);
  74        }
  75        return
  76            res;
  77    }
  78    
  79    public RedBlackTree
  80        union(Map m2) {
  81        return
  82            unionWith(const2m2);
  83    }
  84
  85    // general unionWith by iterating over m2
  86    public RedBlackTree
  87        unionWith(Function2<V,V,V> op,
  88                  Map m2) {
  89        Iterator<KV> i = m2.iterator();
  90        RedBlackTree res = this;
  91
  92        while ( i.hasNext() ) {
  93            KV kv2 = i.next();
  94            K  k2  = kv2.fst;
  95            V  v2  = kv2.snd;
  96            V  v1  = res.lookup(k2);
  97            V  vr  = v1 == null ? v2 : op.apply(v1v2);
  98            res = res.insert(k2vr);
  99        }
 100        return
 101            res;
 102    }
 103
 104    public RedBlackTree
 105        difference(Map m2) {
 106        return
 107            differenceWith(null2m2);
 108    }
 109
 110    // general differenceWith by iterating over m2
 111    public RedBlackTree
 112        differenceWith(Function2<V,V,V> op,
 113                       Map m2) {
 114
 115        Iterator<KV> i = m2.iterator();
 116        RedBlackTree res = this;
 117
 118        while ( i.hasNext() ) {
 119            KV kv2 = i.next();
 120            K  k2  = kv2.fst;
 121            V  v2  = kv2.snd;
 122            V  v1  = res.lookup(k2);
 123
 124            if ( v1 != null ) { // key found in res
 125                V  vr  = op.apply(v1v2);
 126                if ( vr == null )
 127                    res = res.remove(k2);
 128                else
 129                    res = res.insert(k2vr);
 130            }
 131        }
 132        return
 133            res;
 134    }
 135
 136    public RedBlackTree copy() {
 137        return
 138            this;
 139    }
 140
 141    //----------------------------------------
 142    // special binary tree methods
 143    
 144    abstract public int depth();
 145    abstract public int minDepth();
 146    
 147    public boolean member(K k) {
 148        return
 149            lookup(k) != null;
 150    }
 151
 152    //----------------------------------------
 153    // internal methods
 154    
 155    // getter
 156    Node         node()    { return nodeExpected()}
 157    int          color()   { return nodeExpected()}
 158    K            key()     { return nodeExpected()}
 159    V            value()   { return nodeExpected()}
 160    RedBlackTree left()    { return nodeExpected()}
 161    RedBlackTree right()   { return nodeExpected()}
 162
 163    // tree manipulation
 164    public RedBlackTree insert(K kV v) {
 165        assert k != null;
 166        
 167        return
 168            insert1(kv).paintItBlack();
 169    }
 170    
 171    public RedBlackTree remove(K k) {
 172        assert k != null;
 173        
 174        return
 175            remove1(k).paintItBlack();
 176    }
 177    
 178    // 2. iterator for descending enumeration
 179    
 180    abstract public Iterator<KV> iteratorDesc();
 181    
 182    public String toString() {
 183        return 
 184            iterator().toString();
 185    }
 186    
 187    public boolean inv() {
 188        return
 189            invOrdered()
 190            &&
 191            invRedWithBlackChildren()
 192            &&
 193            noOfBlackNodes() != -1
 194            &&
 195            isBlack();
 196    }
 197    
 198    
 199    //----------------------------------------
 200    // internal methods
 201    
 202    abstract RedBlackTree insert1(K kV v);
 203    abstract RedBlackTree remove1(K k);
 204    
 205    abstract boolean invRedWithBlackChildren();
 206    abstract int     noOfBlackNodes();
 207    abstract boolean invOrdered();
 208    abstract boolean allLS(K k);
 209    abstract boolean allGT(K k);
 210    
 211    // helper for ***With functions
 212    private static <A> A nodeExpected() {
 213        return
 214            undefined("Node expected");
 215    }  
 216
 217    private static Function2<V,V,V> const2
 218        = new Function2<V,V,V>() {
 219        public V apply(V xV y) {
 220            return y;
 221        }
 222    };
 223
 224    private static Function2<V,V,V> null2
 225        = new Function2<V,V,V>() {
 226        public V apply(V xV y) {
 227            return null;
 228        }
 229    };
 230    
 231    //----------------------------------------
 232    // coloring
 233
 234    static final int NEGATIVE_BLACK = -1;
 235    static final int RED            = 0;
 236    static final int BLACK          = 1;
 237    static final int DOUBLE_BLACK   = 2;
 238    
 239    static int blacker(int c) {
 240        assert c < DOUBLE_BLACK;
 241        return
 242            c + 1;
 243    }
 244    
 245    static int redder(int c) {
 246        assert c > NEGATIVE_BLACK;
 247        return
 248            c - 1;
 249    }
 250    
 251    boolean isRed()              { return color() == RED;            }
 252    boolean isBlack()            { return color() == BLACK;          }
 253    boolean isDoubleBlack()      { return color() == DOUBLE_BLACK;   }
 254    boolean isNegativeBlack()    { return color() == NEGATIVE_BLACK}
 255    boolean isEmptyDoubleBlack() { return false;                     }
 256    
 257    abstract RedBlackTree paintItRed();
 258    abstract RedBlackTree paintItBlack();
 259    
 260    abstract RedBlackTree blacker();
 261    abstract RedBlackTree redder();
 262    
 263    //----------------------------------------
 264    // the empty tree implemented by applying the singleton design pattern
 265    
 266    // the "generic" empty list object (with a raw type)
 267    
 268    private static final RedBlackTree EMPTY
 269        = new Empty();
 270    
 271    // the singleton class for the empty list object
 272    
 273    private static
 274        class Empty extends RedBlackTree {
 275        
 276        public boolean isEmpty() {
 277            return true;
 278        }
 279
 280        public int size() {
 281            return 0;
 282        }
 283
 284        public int depth() {
 285            return 0;
 286        }
 287
 288        public int minDepth() {
 289            return 0;
 290        }
 291
 292        public V lookup(K k) {
 293            return null;
 294        }
 295        
 296        public KV findMin() {
 297            return nodeExpected();
 298        }  
 299
 300        public KV findMax() {
 301            return nodeExpected();
 302        }  
 303    
 304        public Iterator<KV> iterator() {
 305            ++cntIter;
 306            return
 307                new NullIterator<KV>();
 308        }
 309        public Iterator<KV> iteratorDesc() {
 310            return
 311                iterator();
 312        }
 313        
 314        /* *
 315           public String toString() {
 316           return
 317           ".";
 318           }
 319           /* */
 320        
 321        //----------------------------------------
 322        // not public stuff
 323        
 324        Empty() { }
 325        
 326        boolean invRedWithBlackChildren()  { return true}
 327        int     noOfBlackNodes()           { return 1;    }
 328        boolean invOrdered()               { return true}
 329        boolean allLS(K k)                 { return true}
 330        boolean allGT(K k)                 { return true}
 331        
 332        int color() {
 333            return BLACK;
 334        }
 335        
 336        RedBlackTree insert1(K kV v) {
 337            return
 338                new Node(kvREDEMPTYEMPTY);
 339        }
 340        RedBlackTree remove1(K k) {
 341            return
 342                this;
 343        }
 344        RedBlackTree paintItBlack() {
 345            return
 346                empty()// works also for DoubleEmpty
 347        }
 348        RedBlackTree paintItRed() {
 349            return
 350                undefined("paintItRed on empty tree");
 351        }
 352        RedBlackTree blacker() {
 353            return
 354                doubleEmpty();
 355        }
 356        RedBlackTree redder() {
 357            return
 358                undefined("redder of empty tree");
 359        }
 360        
 361    }
 362    
 363    //----------------------------------------    
 364    // double black empty tree
 365    // helper for deletion
 366    
 367    private static
 368        RedBlackTree doubleEmpty() {
 369        return
 370            DOUBLE_EMPTY;
 371    }
 372    
 373    private static final RedBlackTree DOUBLE_EMPTY
 374        = new DoubleEmpty();
 375    
 376    // the singleton class for the double black empty tree
 377    
 378    private static final
 379        class DoubleEmpty extends Empty {
 380        
 381        /* *
 382           public String toString() {
 383           return
 384           "!";
 385           }
 386           /* */
 387        
 388        DoubleEmpty() { }
 389        
 390        int color() {
 391            return DOUBLE_BLACK;
 392        }
 393
 394        boolean isEmptyDoubleBlack() {
 395            return true;
 396        }
 397        
 398        RedBlackTree blacker() {
 399            return
 400                undefined("blacker of double black");
 401        }
 402        RedBlackTree redder() {
 403            return
 404                empty();
 405        }
 406    }
 407    
 408    //----------------------------------------
 409    // the node class for none empty trees
 410    
 411    private static final
 412        class Node extends RedBlackTree {
 413        
 414        /* persistent */
 415        final K            k;
 416        final V            v;
 417        final int          c// the color
 418        final RedBlackTree l;
 419        final RedBlackTree r;
 420        
 421        /* destructive *
 422        K            k;
 423        V            v;
 424        int          c;
 425        RedBlackTree l;
 426        RedBlackTree r;
 427        /**/
 428        
 429        Node(K kV vint cRedBlackTree lRedBlackTree r) {
 430            assert k != null;
 431            
 432            this.k = k;
 433            this.v = v;
 434            this.c = c;
 435            this.l = l;
 436            this.r = r;
 437            ++cntNode;
 438        }
 439
 440        /* destructive *
 441        public RedBlackTree copy() {
 442            return
 443                new Node(k, v, c, l, r);
 444        }
 445        /**/
 446
 447        /* trc *
 448           String toString() {
 449           return
 450           "(" + l + " " + k + "," + v + "," + c2s(c) + " " + r + ")";
 451           }
 452           /**/
 453
 454        private static String c2s(int c) {
 455            switch ( c ) {
 456            case NEGATIVE_BLACK: return "N";
 457            case RED:            return "R";
 458            case BLACK:          return "B";
 459            case DOUBLE_BLACK:   return "D";
 460            }
 461            return "";
 462        }
 463        
 464        //----------------------------------------
 465        // predicates and attributes
 466        
 467        public boolean isEmpty() {
 468            return false;
 469        }
 470        
 471        public int size() {
 472            return
 473                1 + l.size() + r.size();
 474        }
 475        
 476        public int depth() {
 477            return
 478                1 + max(l.depth()r.depth());
 479        }
 480        
 481        public int minDepth() {
 482            return
 483                1 + min(l.minDepth()r.minDepth());
 484        }
 485        
 486        public V lookup(K k) {
 487            assert k != null;
 488            
 489            switch (signum(k.compareTo(this.k))) {
 490            case -1:
 491                return
 492                    l.lookup(k);
 493            case 0:
 494                return
 495                    v;
 496            case +1:
 497                return
 498                    r.lookup(k);
 499            }
 500            // never executed, but required
 501            return
 502                null;
 503        }
 504        
 505        //----------------------------------------
 506        // getter
 507        
 508        Node         node()  { return this}  
 509        int          color() { return c}
 510        K            key()   { return k}
 511        V            value() { return v}
 512        RedBlackTree left()  { return l}
 513        RedBlackTree right() { return r}
 514        
 515        public KV findMin() {
 516            if ( l.isEmpty() )
 517                return
 518                    mkPair(kv);
 519            return
 520                l.findMin();
 521        }  
 522        
 523        public KV findMax() {
 524            if ( r.isEmpty() )
 525                return
 526                    mkPair(kv);
 527            return
 528                r.findMax();
 529        }  
 530        
 531        public Iterator<KV> iterator() {
 532            ++cntIter;
 533            return
 534                new NodeIterator(this);
 535        }
 536        
 537        public Iterator<KV> iteratorDesc() {
 538            ++cntIter;
 539            return
 540                new NodeIteratorDescending(this);
 541        }
 542        
 543        //----------------------------------------
 544        // invariant helpers
 545        
 546        boolean invRedWithBlackChildren() {
 547            return
 548                ( ! isRed()
 549                  ||
 550                  ( l.isBlack() && r.isBlack() ) )
 551                &&
 552                l.invRedWithBlackChildren()
 553                &&
 554                r.invRedWithBlackChildren();
 555        }
 556        
 557        // -1 indicates # of black nodes differ
 558        int noOfBlackNodes() {
 559            int nl = l.noOfBlackNodes();
 560            int nr = r.noOfBlackNodes();
 561            return
 562                (nl == nr && nl != -1)
 563                ? nl + toInt(isBlack())
 564                : -1;
 565        }
 566        
 567        boolean invOrdered() {
 568            return
 569                l.allLS(k)
 570                &&
 571                r.allGT(k)
 572                &&
 573                l.invOrdered()
 574                &&
 575                r.invOrdered();
 576        }
 577        
 578        boolean allLS(K k) {
 579            return
 580                this.k.compareTo(k) < 0
 581                &&
 582                r.allLS(k)
 583                // &&         // redundant if only
 584                // l.allLS(k) // used by inv
 585                ;
 586        }
 587        boolean allGT(K k) {
 588            return
 589                this.k.compareTo(k) > 0
 590                &&
 591                l.allGT(k)
 592                // &&         // redundant if only
 593                // r.allGT(k) // used by inv
 594                ;
 595        }
 596        
 597        
 598        //----------------------------------------
 599        // getter
 600        
 601        //----------------------------------------
 602        // recoloring
 603        
 604        RedBlackTree paintItBlack() {
 605            return
 606                setColor(BLACK);
 607        }
 608        RedBlackTree paintItRed() {
 609            return
 610                setColor(RED);
 611        }
 612        RedBlackTree blacker() {
 613            return
 614                setColor(blacker(color()));
 615        }
 616        RedBlackTree redder() {
 617            return
 618                setColor(redder(color()));
 619        }
 620        
 621        //----------------------------------------
 622        // balancing
 623        
 624        Node balance(int cRedBlackTree t1K kV vRedBlackTree t2) {
 625            if ( c == BLACK )
 626                return
 627                    balanceBlack(t1kvt2);
 628
 629            // DOUBLE_BLACK only used in remove1
 630            if ( c == DOUBLE_BLACK )
 631                return
 632                    balanceDoubleBlack(t1kvt2);
 633
 634            // no balancing at red nodes
 635            return
 636                set(kvct1t2);
 637        }
 638        
 639        // Okasaki's rules for insertion balancing
 640        
 641        Node balanceBlack(RedBlackTree lK kV vRedBlackTree r) {
 642            // pattern matching with java is pain in the ass
 643            
 644            if ( l.isRed() ) {
 645                Node ln = l.node();
 646                if ( ln.l.isRed() ) {
 647                    Node lln = ln.l.node();
 648                    return
 649                        build3(REDlln.llln.klln.v,
 650                                    lln.r,  ln.k,  ln.v,
 651                                     ln.r,     k,     vrlnlln);
 652                }
 653                if ( ln.r.isRed() ) {
 654                    Node lrn = ln.r.node();
 655                    return
 656                        build3(RED,  ln.l,  ln.k,  ln.v,
 657                                    lrn.llrn.klrn.v,
 658                                    lrn.r,     k,     vrlnlrn);
 659                }
 660            }
 661            if ( r.isRed() ) {
 662                Node rn = r.node();
 663                if ( rn.l.isRed() ) {
 664                    Node rln = rn.l.node();
 665                    return
 666                        build3(RED,
 667                                   l,     k,     v,
 668                               rln.lrln.krln.v,
 669                               rln.r,  rn.k,  rn.v,
 670                                rn.r,
 671                               rlnrn);
 672                }
 673                if ( rn.r.isRed() ) {
 674                    Node rrn = rn.r.node();
 675                    return
 676                        build3(RED,
 677                                   l,     k,     v,
 678                                rn.l,  rn.k,  rn.v,
 679                               rrn.lrrn.krrn.v,
 680                               rrn.r,
 681                               rrnrn);
 682                }
 683            }
 684            return
 685                set(kvBLACKlr);
 686        }
 687        
 688        Node balanceDoubleBlack(RedBlackTree lK kV vRedBlackTree r) {
 689            // same rules as in balanceBlack, double black is absorbed
 690            
 691            if ( l.isRed() ) {
 692                Node ln = l.node();
 693                if ( ln.l.isRed() ) {
 694                    Node lln = ln.l.node();
 695                    return
 696                        build3(BLACK,
 697                               lln.llln.klln.v,
 698                               lln.r,  ln.k,  ln.v,
 699                                ln.r,     k,     v,
 700                                   r,
 701                               lnlln);
 702                }
 703                if ( ln.r.isRed() ) {
 704                    Node lrn = ln.r.node();
 705                    return
 706                        build3(BLACK,
 707                                ln.l,  ln.k,  ln.v,
 708                               lrn.llrn.klrn.v,
 709                               lrn.r,     k,     v,
 710                                   r,
 711                               lnlrn);
 712                }
 713            }
 714            if ( r.isRed() ) {
 715                Node rn = r.node();
 716                if ( rn.l.isRed() ) {
 717                    Node rln = rn.l.node();
 718                    return
 719                        build3(BLACK,
 720                                   l,     k,     v,
 721                               rln.lrln.krln.v,
 722                               rln.r,  rn.k,  rn.v,
 723                                rn.r,
 724                               rlnrn);
 725                }
 726                if ( rn.r.isRed() ) {
 727                    Node rrn = rn.r.node();
 728                    return
 729                        build3(BLACK,
 730                                   l,     k,     v,
 731                                rn.l,  rn.k,  rn.v,
 732                               rrn.lrrn.krrn.v,
 733                               rrn.r,
 734                               rrnrn);
 735                }
 736            }
 737            
 738            // extra rules for negative black none empty trees
 739            if ( r.isNegativeBlack() ) {
 740                Node rn = r.node();
 741                if ( rn.l.isBlack()
 742                     &&
 743                     rn.r.isBlack() ) {
 744                    Node rln = rn.l.node();
 745                    return
 746                        rln.set(rln.krln.vBLACK,
 747                                set(kvBLACKlrln.l),
 748                                rn.balanceBlack(rln.rrn.krn.vrn.r.paintItRed()));
 749                }
 750            }
 751            if ( l.isNegativeBlack() ) {
 752                Node ln = l.node();
 753                if ( ln.l.isBlack()
 754                     &&
 755                     ln.r.isBlack() ) {
 756                    Node lrn = ln.r.node();
 757                    return
 758                        lrn.set(lrn.klrn.vBLACK,
 759                                ln.balanceBlack(ln.l.paintItRed()ln.kln.vlrn.l),
 760                                set(kvBLACKllrn.r));
 761                }
 762            }
 763            return
 764                set(kvDOUBLE_BLACKlr);
 765        }
 766        
 767        Node bubble(int cRedBlackTree lK kV vRedBlackTree r) {
 768            if ( l.isDoubleBlack()
 769                 ||
 770                 r.isDoubleBlack() ) {
 771                return
 772                    balance(blacker(c)l.redder()kvr.redder());
 773            }
 774            return
 775                balance(clkvr);
 776        }
 777        
 778        // build 3 nodes from a b c and d with labels x y z
 779        // when a destrutive set is used
 780        // the root is stored in this
 781        // the left node is stored in l
 782        // the right node in r
 783        
 784        Node build3(int rootColor,
 785                    RedBlackTree aK xkV xv,
 786                    RedBlackTree bK ykV yv,
 787                    RedBlackTree cK zkV zv,
 788                    RedBlackTree d,
 789                    Node lNode r) {
 790            return
 791                set(ykyvrootColor,
 792                    l.set(xkxvBLACKab),
 793                    r.set(zkzvBLACKcd));
 794        }
 795        
 796        //----------------------------------------
 797        // setter
 798        
 799        private Node set(K kV vint c,
 800                         RedBlackTree l,
 801                         RedBlackTree r) {
 802            /* persistent */
 803            if ( k == this.k && v == this.v
 804                 &&
 805                 c == this.c
 806                 &&
 807                 l == this.l && r == this.r )
 808                return
 809                    this;
 810            return
 811                new Node(kvclr);
 812            
 813            /* destructive *
 814            this.k = k;
 815            this.v = v;
 816            this.c = c;
 817            this.l = l;
 818            this.r = r;
 819            return
 820                this;
 821            /**/
 822        }
 823        private Node setV(V v) {
 824            /* persistent */
 825            return
 826                ( v == this.v )
 827                ? this
 828                : new Node(this.kvthis.cthis.lthis.r);
 829            
 830            /* destructive *
 831            this.v = v;
 832            return
 833                this;
 834            /**/
 835        }
 836        
 837        private Node setColor(int c) {
 838            /* persistent */
 839            return
 840                c == this.c
 841                ? this
 842                : new Node(this.kthis.vcthis.lthis.r);
 843            
 844            /* destructive *
 845               this.c = c;
 846               return
 847               this;
 848               /**/
 849        }
 850        
 851        //----------------------------------------
 852        // tree manipulation
 853        
 854        RedBlackTree insert1(K kV v) {
 855            switch ( signum(k.compareTo(this.k)) ) {
 856            case -1:
 857                return
 858                    balance(cl.insert1(kv)this.kthis.vr);
 859            case 0:
 860                return
 861                    setV(v);
 862            case +1:
 863                return
 864                    balance(clthis.kthis.vr.insert1(kv));
 865            }
 866            // never executed, but required
 867            return
 868                null;
 869        }
 870        
 871        RedBlackTree remove1(K k) {
 872            switch ( signum(k.compareTo(this.k)) ) {
 873            case -1:
 874                return
 875                    bubble(cl.remove1(k)this.kthis.vr);
 876            case 0:
 877                return
 878                    removeRoot();
 879                //trc("removeRoot",removeRoot());
 880            case +1:
 881                return
 882                    bubble(clthis.kthis.vr.remove1(k));
 883            }
 884            // never executed, but required
 885            return
 886                null;
 887        }
 888        
 889        RedBlackTree removeRoot() {
 890            if ( isRed()
 891                 &&
 892                 l.isEmpty()
 893                 &&
 894                 r.isEmpty()
 895                 )
 896                return
 897                    empty();
 898            if ( isBlack() ) {
 899                if ( l.isEmpty()
 900                     &&
 901                     r.isEmpty() )
 902                    return
 903                        doubleEmpty();
 904                if ( l.isRed()
 905                     &&
 906                     r.isEmpty() )
 907                    return
 908                        l.blacker();
 909                if ( r.isRed()
 910                     &&
 911                     l.isEmpty() )
 912                    return
 913                        r.blacker();
 914            }
 915            KV p = l.findMax();
 916            return
 917                bubble(cl.node().removeMax()p.fstp.sndr);
 918        }
 919        
 920        RedBlackTree removeMax() {
 921            if ( r.isEmpty() )
 922                return
 923                    removeRoot();
 924            return
 925                bubble(clkvr.node().removeMax());
 926        }
 927        
 928        //----------------------------------------
 929        // iterators
 930        
 931        // ascending enumeration
 932        
 933        private static
 934            class NodeIterator
 935            extends ds.util.Iterator<KV> {
 936            
 937            Queue queue;
 938            
 939            NodeIterator(Node n) {
 940                queue = Queue.empty();
 941                add(n);
 942                ++cntIter;
 943            }
 944            
 945            void add(Node n) {
 946                queue = queue.cons(n);
 947                if ( ! n.l.isEmpty() )
 948                    add(n.l.node())// downcast
 949            }
 950            
 951            void addSubNodes(Node n) {
 952                if ( ! n.r.isEmpty() )
 953                    add(n.r.node());
 954            }
 955            
 956            public boolean hasNext() {
 957                return
 958                    ! queue.isEmpty();
 959            }
 960            
 961            public KV next() {
 962                if ( queue.isEmpty() )
 963                    return
 964                        undefined("empty tree");
 965                
 966                Node n = (Node)queue.head();
 967                queue  = queue.tail();
 968                addSubNodes(n);
 969                return
 970                    mkPair(n.kn.v);
 971            }
 972        }
 973        
 974        // descending enumeration
 975        
 976        private
 977            class NodeIteratorDescending
 978            extends NodeIterator {
 979            
 980            NodeIteratorDescending(Node n) {
 981                super(n);
 982            }
 983            
 984            void add(Node n) {
 985                queue = queue.cons(n);
 986                if ( ! n.r.isEmpty() )
 987                    add(n.r.node())// downcast
 988            }
 989            
 990            void addSubNodes(Node n) {
 991                if ( ! n.l.isEmpty() )
 992                    add(n.l.node());
 993            }
 994        }
 995    }
 996    
 997    //----------------------------------------
 998    // profiling
 999    
1000    private static int cntNode = 0;
1001    private static int cntIter = 0;
1002    
1003    public static String stats() {
1004        return
1005            "stats for ds.persistent.map.RedBlackTree:\n" +
1006            "# new Node()               : " + cntNode + "\n" +
1007            "# new Iterator()           : " + cntIter + "\n";
1008    }
1009    
1010    public String objStats() {
1011        int s = size();
1012        int o = s;
1013        int f = 5 * s;
1014        int m = o + f;
1015        
1016        return
1017            "mem stats for ds.persistent.map.RedBlackTree object:\n" +
1018            "# elements (size)      : " + s + "\n" +
1019            "# objects              : " + o + "\n" +
1020            "# fields               : " + f + "\n" +
1021            "# mem words            : " + m + "\n";
1022    }
1023}
weiter
Quellen
weiter

Letzte Änderung: 05.11.2015
© Prof. Dr. Uwe Schmidt
Prof. Dr. Uwe Schmidt FH Wedel