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 }