zoukankan      html  css  js  c++  java
  • 十、红黑树

      1 package rbtree;
      2 
      3 public class RBTree<K extends Comparable<K>, V> {
      4     private static final boolean RED = true;
      5     private static final boolean BLACK = false;
      6     private RBNode root;//根节点
      7 
      8 
      9     //寻找当前节点的父节点parentOf()
     10     private RBNode parentOf(RBNode node) {
     11         if (node != null) {
     12             return node.parent;
     13         }
     14         return null;
     15     }
     16 
     17     //判断当前节点是否为红色
     18     private boolean isRed(RBNode node) {
     19         if (node != null) {
     20             return node.color == RED;
     21         }
     22         return false;
     23     }
     24 
     25     //判断当前节点是否为黑色
     26     private boolean isBlack(RBNode node) {
     27         if (node != null) {
     28             return node.color == BLACK;
     29         }
     30         return false;
     31     }
     32 
     33     //设置节点成红色
     34     private void setRed(RBNode node) {
     35         if (node != null) {
     36             node.color = RED;
     37         }
     38     }
     39 
     40     //设置节点成黑色
     41     private void setBlack(RBNode node) {
     42         if (node != null) {
     43             node.color = BLACK;
     44         }
     45     }
     46 
     47     //中序遍历
     48     public void inOrderPrint() {
     49         inOrderPrint(this.root);
     50     }
     51 
     52     //内部中序遍历
     53     private void inOrderPrint(RBNode node) {
     54         if (node != null) {
     55             inOrderPrint(node.left);
     56             System.out.println("key:" + node.key + ",value:" + node.value);
     57             inOrderPrint(node.right);
     58         }
     59     }
     60 
     61     //左旋
     62 
     63     /**
     64      * p                           p
     65      * |                           |
     66      * x                           y
     67      * /        -->               / 
     68      * lx   y                       x   ry
     69      * /                      / 
     70      * ly   ry                 lx   ly
     71      * <p>
     72      * 1.将ly设置成x的右子节点
     73      * 2.将x的父节点设置成y的父节点
     74      * 3.将y的左子节点设置成x
     75      */
     76     private void leftRotate(RBNode x) {
     77         if (x != null) {
     78             RBNode y = x.right;
     79             //1.
     80             if (y != null) {
     81                 x.right = y.left;
     82                 RBNode ly = y.left;
     83                 if (ly != null) {
     84                     ly.parent = x;
     85                 }
     86                 //2.
     87                 if (x.parent != null) {
     88                     y.parent = x.parent;
     89                     if (x.parent.left == x) {
     90                         x.parent.left = y;
     91                     } else {
     92                         x.parent.right = y;
     93                     }
     94                 } else {
     95                     this.root = y;
     96                 }
     97                 //3.
     98                 y.left = x;
     99                 x.parent = y;
    100             } else {
    101                 return;
    102             }
    103         } else {
    104             return;
    105         }
    106     }
    107 
    108     //右旋
    109 
    110     /**
    111      * p                           p
    112      * |                           |
    113      * x                           y
    114      * /        -->               / 
    115      * y   lx                     ly   x
    116      * /                              / 
    117      * ly   ry                         ry   lx
    118      * <p>
    119      * 1.将ry设置成x的右子节点
    120      * 2.将x的父节点设置成y的父节点
    121      * 3.将y的右子节点设置成x
    122      */
    123     private void rightRotate(RBNode x) {
    124         if (x == null) {
    125             return;
    126         } else {
    127             RBNode y = x.left;
    128             if (y == null) {
    129                 return;
    130             } else {
    131                 //1.
    132                 RBNode ry = y.right;
    133                 x.left = ry;
    134                 if (ry != null) {
    135                     ry.parent = x;
    136                 }
    137                 //2.
    138                 if (x.parent != null) {
    139                     y.parent = x.parent;
    140                     if (x.parent.left == x) {
    141                         x.parent.left = y;
    142                     } else {
    143                         x.parent.right = y;
    144                     }
    145                 } else {
    146                     this.root = y;
    147                 }
    148                 //3.
    149                 y.right = x;
    150                 x.parent = y;
    151             }
    152         }
    153     }
    154 
    155     //外部插入方法
    156     public void insert(K key, V value) {
    157         //将key和value封装成一个node对象
    158         RBNode node = new RBNode();
    159         node.setKey(key);
    160         node.setValue(value);
    161         node.setColor(RED);
    162         insert(node);
    163     }
    164 
    165     //内部插入方法
    166     private void insert(RBNode node) {
    167         RBNode parent = null;
    168         RBNode temp = this.root;//临时变量,为找到当前node的父节点
    169         while (temp != null) {
    170             parent = temp;
    171             int cmp = node.key.compareTo(temp.key);
    172             if (cmp > 0) {//当前node.key比parent大
    173                 temp = temp.right;
    174             } else if (cmp == 0) {//当前node.key等于parent,直接更新parent的value值
    175                 temp.setValue(node.getValue());
    176                 return;
    177             } else {//当前node.key比parent小
    178                 temp = temp.left;
    179             }
    180         }
    181         node.parent = parent;
    182         if (parent != null) {
    183             int cmp = node.key.compareTo(parent.key);
    184             if (cmp > 0) {
    185                 parent.right = node;//node插入到右面
    186             } else {
    187                 parent.left = node;//node插入到左面
    188             }
    189         } else {
    190             this.root = node;
    191         }
    192 
    193         //插入后会破坏红黑树的平衡,需要调用修复平衡的方法insertFixup()
    194         insertFixUp(node);
    195 
    196     }
    197 
    198 
    199     /**
    200      * 插入后修复红黑树的方法
    201      * |--情景1:红黑树为空树,将根节点染色为黑色
    202      * |--情景2:插入节点的key已经存在,不需要处理
    203      * |--情景3:插入节点的父节点为黑色,因为所插入的路径上的黑色节点没有变化,所以不用处理
    204      * |--情景4:插入节点的父节点为红色,需要我们处理:
    205      * |--4.1:叔叔节点存在,并且为红色(父-叔 双红),将爸爸和叔叔染色为黑色,再将爷爷染色为红色,并且再以
    206      * 爷爷为当前节点,进行下一轮的处理
    207      * |--4.2:叔叔节点不存在,或者为黑色,父节点为爷爷节点的左子树
    208      * |--4.2.1:插入节点为其父节点的左子节点(LL情况),将爸爸染色为黑色,将爷爷染色为红色,然后以爷爷节点右旋,就完成了
    209      * |--4.2.2:插入节点为其父节点的右子节点(LR情况),以爸爸节点进行一次左旋,得到4.2.1的情况
    210      * 然后以爸爸节点为当前节点,进行下一轮操作
    211      * |--4.3:叔叔节点不存在,或者为黑色,父节点为爷爷节点的右子树
    212      * |--4.3.1:插入节点为其父节点的右子节点(RR情况),将爸爸染色为黑色,将爷爷染色为红色,然后以爷爷节点左旋,就完成了
    213      * |--4.3.2:插入节点为其父节点的左子节点(Rl情况),以爸爸节点进行一次右旋,得到4.2.1的情况
    214      * *                  然后以爸爸节点为当前节点,进行下一轮操作
    215      */
    216     private void insertFixUp(RBNode node) {
    217         RBNode parent = parentOf(node);
    218         RBNode gparent = parentOf(parent);
    219         if (parent != null && isRed(parent)) {
    220             //如果父节点为红色,那么一定有根节点,因为根节点不可能为红色
    221             RBNode uncle = null;
    222             //
    223             if (parent == gparent.left) {//父节点为爷爷节点的左子树
    224                 uncle = gparent.right;
    225                 if (uncle != null && isRed(uncle)) {
    226                     setBlack(parent);
    227                     setBlack(uncle);
    228                     setRed(gparent);
    229                     insertFixUp(gparent);
    230                     return;
    231                 }
    232                 if (uncle == null || isBlack(uncle)) {
    233                     if (node == parent.left) {
    234                         setBlack(parent);
    235                         setRed(gparent);
    236                         rightRotate(gparent);
    237                         return;
    238                     }
    239                     if (node == parent.right) {
    240                         leftRotate(parent);
    241                         insertFixUp(parent);
    242                         return;
    243                     }
    244                 }
    245             } else {//父节点为爷爷节点的右子树
    246                 uncle = gparent.left;
    247                 if (uncle != null && isRed(uncle)) {
    248                     setBlack(parent);
    249                     setBlack(uncle);
    250                     setRed(gparent);
    251                     insertFixUp(gparent);
    252                     return;
    253                 }
    254                 if (uncle == null || isBlack(uncle)) {
    255                     if (node == parent.right) {
    256                         setBlack(parent);
    257                         setRed(gparent);
    258                         leftRotate(gparent);
    259                         return;
    260                     }
    261                     if (node == parent.left) {
    262                         rightRotate(parent);
    263                         insertFixUp(parent);
    264                         return;
    265                     }
    266                 }
    267             }
    268         }
    269 
    270     }
    271 
    272     static class RBNode<K extends Comparable<K>, V> {
    273         private RBNode parent;
    274         private RBNode left;
    275         private RBNode right;
    276         private boolean color;
    277         private K key;
    278         private V value;
    279 
    280         public RBNode() {
    281         }
    282 
    283         public RBNode(RBNode parent, RBNode left, RBNode right, boolean color, K key, V value) {
    284             this.parent = parent;
    285             this.left = left;
    286             this.right = right;
    287             this.color = color;
    288             this.key = key;
    289             this.value = value;
    290         }
    291 
    292         public RBNode getParent() {
    293             return parent;
    294         }
    295 
    296         public void setParent(RBNode parent) {
    297             this.parent = parent;
    298         }
    299 
    300         public RBNode getLeft() {
    301             return left;
    302         }
    303 
    304         public void setLeft(RBNode left) {
    305             this.left = left;
    306         }
    307 
    308         public RBNode getRight() {
    309             return right;
    310         }
    311 
    312         public void setRight(RBNode right) {
    313             this.right = right;
    314         }
    315 
    316         public boolean isColor() {
    317             return color;
    318         }
    319 
    320         public void setColor(boolean color) {
    321             this.color = color;
    322         }
    323 
    324         public K getKey() {
    325             return key;
    326         }
    327 
    328         public void setKey(K key) {
    329             this.key = key;
    330         }
    331 
    332         public V getValue() {
    333             return value;
    334         }
    335 
    336         public void setValue(V value) {
    337             this.value = value;
    338         }
    339     }
    340 
    341 }
  • 相关阅读:
    LinQ&EF任我行(一)LinQ to SQL (转)
    WPF数据模板和控件模板
    Sql优化
    SQL锁表语句
    js动态创建dom
    js实现等待n秒后按钮可用
    js关于事件冒泡
    工作流学习(个人总结)
    sql常用函数
    将Datatable序列化为Json对象返回到客户端
  • 原文地址:https://www.cnblogs.com/zsy-code/p/13810686.html
Copyright © 2011-2022 走看看