github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/petar/GoLLRB/doc/Sedgewick-RedBlackBST.java (about)

     1  public class RedBlackBST<Key extends Comparable<Key>, Value> 
     2  {
     3     private static final int BST = 0;
     4     private static final int TD234 = 1;
     5     private static final int BU23 = 2;
     6     private static final boolean RED   = true;
     7     private static final boolean BLACK = false;
     8  
     9     private Node root;            // root of the BST
    10     private int k;                // ordinal for drawing
    11     private final int species;    // species kind of tree for insert
    12     private int heightBLACK;      // black height of tree 
    13  
    14     RedBlackBST(int species)
    15     {  this.species = species;  }
    16  
    17     private class Node
    18     {
    19        Key key;                  // key
    20        Value value;              // associated data
    21        Node left, right;         // left and right subtrees
    22        boolean color;            // color of parent link
    23        private int N;            // number of nodes in tree rooted here
    24        private int height;       // height of tree rooted here
    25        private double xc, yc;    // for drawing
    26  
    27        Node(Key key, Value value)
    28        {
    29           this.key   = key;
    30           this.value = value;
    31           this.color = RED;
    32           this.N = 1;
    33           this.height = 1;
    34        }
    35     }
    36  
    37     public int size()
    38     {  return size(root);  }
    39  
    40     private int size(Node x)
    41     { 
    42        if (x == null) return 0;
    43        else           return x.N;
    44     }
    45  
    46     public int rootRank()
    47     { 
    48         if (root == null) return 0;
    49         else              return size(root.left);
    50     }
    51  
    52     public int height()
    53     {  return height(root);  }
    54  
    55     public int heightB()
    56     {  return heightBLACK;  }
    57  
    58     private int height(Node x)
    59     { 
    60        if (x == null) return 0;
    61        else           return x.height;
    62     }
    63  
    64     public boolean contains(Key key)
    65     {  return (get(key) != null);  }
    66  
    67     public Value get(Key key)
    68     {  return get(root, key);  }
    69  
    70     private Value get(Node x, Key key)
    71     {
    72        if (x == null)        return null;
    73        if (eq  (key, x.key)) return x.value;
    74        if (less(key, x.key)) return get(x.left,  key);
    75        else                  return get(x.right, key);
    76     }
    77  
    78     public Key min()
    79     {  
    80        if (root == null) return null;
    81        else              return min(root);
    82     }
    83  
    84     private Key min(Node x)
    85     {
    86        if (x.left == null) return x.key;
    87        else                return min(x.left);
    88     }
    89  
    90     public Key max()
    91     {  
    92        if (root == null) return null;
    93        else              return max(root);
    94     }
    95  
    96     private Key max(Node x)
    97     {
    98        if (x.right == null) return x.key;
    99        else                 return max(x.right);
   100     }
   101  
   102     public void put(Key key, Value value)
   103     {
   104        root = insert(root, key, value);
   105        if (isRed(root)) heightBLACK++;
   106        root.color = BLACK;
   107     }
   108  
   109     private Node insert(Node h, Key key, Value value)
   110     { 
   111        if (h == null) 
   112           return new Node(key, value);
   113  
   114        if (species == TD234) 
   115           if (isRed(h.left) && isRed(h.right))
   116  	     colorFlip(h);
   117  
   118        if (eq(key, h.key))
   119           h.value = value;
   120        else if (less(key, h.key)) 
   121           h.left = insert(h.left, key, value); 
   122        else 
   123           h.right = insert(h.right, key, value); 
   124  
   125        if (species == BST) return setN(h);
   126  
   127        if (isRed(h.right))
   128           h = rotateLeft(h);
   129  
   130        if (isRed(h.left) && isRed(h.left.left))
   131           h = rotateRight(h);
   132  
   133        if (species == BU23)
   134           if (isRed(h.left) && isRed(h.right))
   135  	     colorFlip(h);
   136  
   137        return setN(h);
   138     }
   139  
   140     public void deleteMin()
   141     {
   142        root = deleteMin(root);
   143        root.color = BLACK;
   144     }
   145  
   146     private Node deleteMin(Node h)
   147     { 
   148        if (h.left == null)
   149           return null;
   150  
   151        if (!isRed(h.left) && !isRed(h.left.left))
   152           h = moveRedLeft(h);
   153  
   154        h.left = deleteMin(h.left);
   155  
   156        return fixUp(h);
   157     }
   158  
   159     public void deleteMax()
   160     {
   161        root = deleteMax(root);
   162        root.color = BLACK;
   163     }
   164  
   165     private Node deleteMax(Node h)
   166     { 
   167         //      if (h.right == null)
   168  	  //      {  
   169  	  //         if (h.left != null)
   170  	  //            h.left.color = BLACK;
   171  	  //         return h.left;
   172  	  //      }
   173  
   174        if (isRed(h.left))
   175           h = rotateRight(h);
   176  
   177        if (h.right == null)
   178           return null;
   179  
   180        if (!isRed(h.right) && !isRed(h.right.left))
   181           h = moveRedRight(h);
   182  
   183        h.right = deleteMax(h.right);
   184  
   185        return fixUp(h);
   186     }
   187  
   188     public void delete(Key key)
   189     { 
   190        root = delete(root, key);
   191        root.color = BLACK;
   192     }
   193  
   194     private Node delete(Node h, Key key)
   195     { 
   196        if (less(key, h.key)) 
   197        {
   198           if (!isRed(h.left) && !isRed(h.left.left))
   199              h = moveRedLeft(h);
   200           h.left =  delete(h.left, key);
   201        }
   202        else 
   203        {
   204           if (isRed(h.left)) 
   205              h = rotateRight(h);
   206           if (eq(key, h.key) && (h.right == null))
   207              return null;
   208           if (!isRed(h.right) && !isRed(h.right.left))
   209              h = moveRedRight(h);
   210           if (eq(key, h.key))
   211           {
   212              h.value = get(h.right, min(h.right));
   213              h.key = min(h.right);
   214  	    h.right = deleteMin(h.right);
   215           }
   216           else h.right = delete(h.right, key);
   217        }
   218   
   219        return fixUp(h);
   220     }
   221  
   222  // Helper methods
   223  
   224      private boolean less(Key a, Key b) { return a.compareTo(b) <  0; }
   225      private boolean eq  (Key a, Key b) { return a.compareTo(b) == 0; }
   226  
   227      private boolean isRed(Node x)
   228      {
   229          if (x == null) return false;
   230          return (x.color == RED);
   231      }
   232  
   233     private void colorFlip(Node h)
   234     {  
   235        h.color        = !h.color;
   236        h.left.color   = !h.left.color;
   237        h.right.color  = !h.right.color;
   238     }
   239  
   240     private Node rotateLeft(Node h)
   241     {  // Make a right-leaning 3-node lean to the left.
   242        Node x = h.right;
   243        h.right = x.left;
   244        x.left = setN(h);
   245        x.color      = x.left.color;                   
   246        x.left.color = RED;                     
   247        return setN(x);
   248     }
   249  
   250     private Node rotateRight(Node h)
   251     {  // Make a left-leaning 3-node lean to the right.
   252        Node x = h.left;
   253        h.left = x.right;
   254        x.right = setN(h);
   255        x.color       = x.right.color;                   
   256        x.right.color = RED;                     
   257        return setN(x);
   258      }
   259  
   260      private Node moveRedLeft(Node h)
   261      {  // Assuming that h is red and both h.left and h.left.left
   262         // are black, make h.left or one of its children red.
   263         colorFlip(h);
   264         if (isRed(h.right.left))
   265         { 
   266            h.right = rotateRight(h.right);
   267            h = rotateLeft(h);
   268            colorFlip(h);
   269         }
   270        return h;
   271      }
   272  
   273      private Node moveRedRight(Node h)
   274      {  // Assuming that h is red and both h.right and h.right.left
   275         // are black, make h.right or one of its children red.
   276         colorFlip(h);
   277         if (isRed(h.left.left))
   278         { 
   279            h = rotateRight(h);
   280  	  colorFlip(h);
   281         }
   282         return h;
   283      }
   284  
   285     private Node fixUp(Node h)
   286     {
   287        if (isRed(h.right))
   288           h = rotateLeft(h);
   289  
   290        if (isRed(h.left) && isRed(h.left.left))
   291           h = rotateRight(h);
   292  
   293        if (isRed(h.left) && isRed(h.right))
   294           colorFlip(h);
   295  
   296        return setN(h);
   297     }
   298        
   299     private Node setN(Node h)
   300     {
   301        h.N = size(h.left) + size(h.right) + 1;
   302        if (height(h.left) > height(h.right)) h.height = height(h.left) + 1;
   303        else                                  h.height = height(h.right) + 1;
   304        return h;
   305     }
   306        
   307     public String toString()
   308     {  
   309        if (root == null) return "";
   310        else              return heightB() + " " + toString(root);  
   311     }
   312  
   313     public String toString(Node x)
   314     {  
   315        String s = "(";
   316        if (x.left == null) s += "("; else s += toString(x.left);
   317        if (isRed(x)) s += "*";
   318        if (x.right == null) s += ")"; else s += toString(x.right);
   319        return s + ")";
   320     }
   321  
   322  // Methods for tree drawing
   323  
   324      public void draw(double y, double lineWidth, double nodeSize)
   325      { 
   326        k = 0; 
   327        setcoords(root, y);
   328        StdDraw.setPenColor(StdDraw.BLACK);
   329        StdDraw.setPenRadius(lineWidth);
   330        drawlines(root); 
   331        StdDraw.setPenColor(StdDraw.WHITE);
   332        drawnodes(root, nodeSize); 
   333      }
   334  
   335      public void setcoords(Node x, double d)
   336      {
   337          if (x == null) return;
   338          setcoords(x.left, d-.04);
   339          x.xc = (0.5 + k++)/size(); x.yc = d - .04;
   340          setcoords(x.right, d-.04);
   341      }
   342  
   343      public void drawlines(Node x)
   344      {
   345          if (x == null) return;
   346          drawlines(x.left);
   347          if (x.left != null)
   348          {
   349  	    if (x.left.color == RED) StdDraw.setPenColor(StdDraw.RED);
   350  	    else StdDraw.setPenColor(StdDraw.BLACK);
   351              StdDraw.line(x.xc, x.yc, x.left.xc, x.left.yc);
   352          }
   353          if (x.right != null)
   354          {
   355  	    if (x.right.color == RED) StdDraw.setPenColor(StdDraw.RED);
   356  	    else StdDraw.setPenColor(StdDraw.BLACK);
   357              StdDraw.line(x.xc, x.yc, x.right.xc, x.right.yc);
   358          }
   359          drawlines(x.right);
   360      }
   361  
   362      public void drawnodes(Node x, double nodeSize)
   363      {
   364          if (x == null) return;
   365          drawnodes(x.left, nodeSize);
   366  	StdDraw.filledCircle(x.xc, x.yc, nodeSize);
   367          drawnodes(x.right, nodeSize);
   368      }
   369  
   370      public void mark(Key key)
   371      { 
   372        StdDraw.setPenColor(StdDraw.BLACK);
   373        marknodes(key, root); 
   374      }
   375  
   376      public void marknodes(Key key, Node x)
   377      {
   378          if (x == null) return;
   379          marknodes(key, x.left);
   380  	if (eq(key, x.key))
   381             StdDraw.filledCircle(x.xc, x.yc, .004);
   382          marknodes(key, x.right);
   383      }
   384  
   385      public int ipl()
   386      {  return ipl(root);  }
   387  
   388      public int ipl(Node x)
   389      {
   390  	if (x == null) return 0;
   391  	return size(x) - 1 + ipl(x.left) + ipl(x.right);
   392      }
   393         
   394      public int sizeRed()
   395      {  return sizeRed(root);  }
   396  
   397      public int sizeRed(Node x)
   398      {
   399  	if (x == null) return 0;
   400          if (isRed(x)) return 1 + sizeRed(x.left) + sizeRed(x.right);
   401          else          return sizeRed(x.left) + sizeRed(x.right);
   402      }
   403         
   404  // Integrity checks
   405  
   406     public boolean check() 
   407     {  // Is this tree a red-black tree?
   408        return isBST() && is234() && isBalanced();
   409     }
   410  
   411     private boolean isBST() 
   412     {  // Is this tree a BST?
   413        return isBST(root, min(), max());
   414     }
   415  
   416     private boolean isBST(Node x, Key min, Key max)
   417     {  // Are all the values in the BST rooted at x between min and max,
   418        // and does the same property hold for both subtrees?
   419        if (x == null) return true;
   420        if (less(x.key, min) || less(max, x.key)) return false;
   421        return isBST(x.left, min, x.key) && isBST(x.right, x.key, max);
   422     } 
   423  
   424     private boolean is234() { return is234(root); }
   425     private boolean is234(Node x)
   426     {  // Does the tree have no red right links, and at most two (left)
   427        // red links in a row on any path?
   428        if (x == null) return true;
   429        if (isRed(x.right)) return false;
   430        if (isRed(x))
   431          if (isRed(x.left))
   432            if (isRed(x.left.left)) return false;
   433        return is234(x.left) && is234(x.right);
   434     } 
   435  
   436     private boolean isBalanced()
   437     { // Do all paths from root to leaf have same number of black edges?
   438        int black = 0;     // number of black links on path from root to min
   439        Node x = root;
   440        while (x != null)
   441        {
   442           if (!isRed(x)) black++;
   443              x = x.left;
   444        }
   445        return isBalanced(root, black);
   446     }
   447  
   448     private boolean isBalanced(Node x, int black)
   449     { // Does every path from the root to a leaf have the given number 
   450       // of black links?
   451        if      (x == null && black == 0) return true;
   452        else if (x == null && black != 0) return false;
   453        if (!isRed(x)) black--;
   454        return isBalanced(x.left, black) && isBalanced(x.right, black);
   455     } 
   456  
   457  
   458    public static void main(String[] args)
   459    {
   460        StdDraw.setPenRadius(.0025);
   461        int species = Integer.parseInt(args[0]);
   462        RedBlackBST<Integer, Integer> st;
   463        st = new RedBlackBST<Integer, Integer>(species);
   464        int[] a = { 3, 1, 4, 2, 5, 9, 6, 8, 7 };
   465        for (int i = 0; i < a.length; i++)
   466  	  st.put(a[i], i);
   467        StdOut.println(st);
   468        StdDraw.clear(StdDraw.LIGHT_GRAY);
   469        st.draw(.95, .0025, .008);
   470        StdOut.println(st.min() + " " + st.max() + " " + st.check());
   471        StdOut.println(st.ipl());
   472        StdOut.println(st.heightB());
   473    }
   474  
   475  }