红黑树也是一种平衡二叉查找树,经常用于替代AVL树,特点如下:
- 根节点为黑色的,空节点也看做黑色节点;
- 红色节点的子节点一定为黑色,任何一条路径不能出现两个连续的红节点;
- 从任何一个节点出发,到空节点的路径上包含相同数目的黑节点,即如果忽略路径中的红色节点,红黑树是完全平衡的。
相对于AVL树,红黑树能够以O(log2 n) 的时间复杂度进行搜索、插入、删除操作。此外,由于它的设计,任何不平衡都会在三次旋转之内解决。当然,红黑树并不适应所有应用树的领域。如果数据基本上是静态的,那么让他们待在他们能够插入,并且不影响平衡的地方会具有更好的性能。如果数据完全是静态的,例如,做一个哈希表,性能可能会更好一些。
红黑树是一个更高效的检索二叉树,因此常常用来实现关联数组。典型地,JDK 提供的集合类 TreeMap 本身就是一个红黑树的实现。对于 TreeMap 而言,由于它底层采用一棵“红黑树”来保存集合中的 Entry,这意味这 TreeMap 添加元素、取出元素的性能都比 HashMap 低:当 TreeMap 添加元素时,需要通过循环找到新增 Entry 的插入位置,因此比较耗性能;当从 TreeMap 中取出元素时,需要通过循环才能找到合适的 Entry,也比较耗性能。但 TreeMap、TreeSet (TreeSet 底层是通过 TreeMap 来实现的)比 HashMap、HashSet 的优势在于:TreeMap 中的所有 Entry 总是按 key 根据指定排序规则保持有序状态,TreeSet 中所有元素总是根据指定排序规则保持有序状态。
用途:
AVL树:最早的平衡二叉树之一。应用相对其他数据结构比较少。windows对进程地址空间的管理用到了AVL树
红黑树:平衡二叉树,广泛用在C++的STL中。map和set都是用红黑树实现的。
B/B+树用在磁盘文件组织 数据索引和数据库索引
插入、删除思路:《算法导论》第13章
Java实现如下:

1 package com.tonyluis; 2 3 public class RBTree { 4 5 //空节点 6 private final Node NIL = new Node(null,null,null,Color.BLACK,-1); 7 private Node root; 8 9 public RBTree() { 10 root = NIL; 11 } 12 13 public RBTree(Node root) { 14 this.root = root; 15 } 16 17 18 //插入节点 19 public void rbInsert(Node node) { 20 21 Node previous = NIL; 22 Node temp = root; 23 24 while (temp != NIL) { 25 previous = temp; 26 if (temp.getValue() < node.getValue()) { 27 temp = temp.getRight(); 28 } else { 29 temp = temp.getLeft(); 30 } 31 } 32 node.setParent(previous); 33 34 if (previous == NIL) { 35 root = node; 36 root.setParent(NIL); 37 } else if (previous.getValue() > node.getValue()) { 38 previous.setLeft(node); 39 } else { 40 previous.setRight(node); 41 } 42 43 node.setLeft(NIL); 44 node.setRight(NIL); 45 node.setColor(Color.RED); 46 rb_Insert_Fixup(node); 47 48 } 49 50 //插入节点后的调整 51 private void rb_Insert_Fixup(Node node) { 52 53 while (node.getParent().getColor() == Color.RED) { 54 55 if (node.getParent() == node.getParent().getParent().getLeft()) { 56 57 Node rightNuncle = node.getParent().getParent().getRight(); 58 59 if (rightNuncle.getColor() == Color.RED) { //Case 1 60 61 rightNuncle.setColor(Color.BLACK); 62 node.getParent().setColor(Color.BLACK); 63 node.getParent().getParent().setColor(Color.RED); 64 node = node.getParent().getParent(); 65 66 } else if (node == node.getParent().getRight()) { //case 2 67 68 node = node.getParent(); 69 leftRotate(node); 70 71 } else { //case 3 72 73 node.getParent().setColor(Color.BLACK); 74 node.getParent().getParent().setColor(Color.RED); 75 76 rightRotate(node.getParent().getParent()); 77 78 } 79 80 } else { 81 82 Node leftNuncle = node.getParent().getParent().getLeft(); 83 84 if (leftNuncle.getColor() == Color.RED) { //case 4 85 86 leftNuncle.setColor(Color.BLACK); 87 node.getParent().setColor(Color.BLACK); 88 node.getParent().getParent().setColor(Color.RED); 89 node = node.getParent().getParent(); 90 91 } else if (node == node.getParent().getLeft()) { //case 5 92 93 node = node.getParent(); 94 rightRotate(node); 95 96 } else { // case 6 97 98 node.getParent().setColor(Color.BLACK); 99 node.getParent().getParent().setColor(Color.RED); 100 leftRotate(node.getParent().getParent()); 101 102 } 103 104 } 105 106 107 } 108 109 root.setColor(Color.BLACK); 110 111 } 112 113 114 //删除节点 115 public Node rbDelete(int data) { 116 117 Node node = search(data); 118 Node temp = NIL; 119 Node child = NIL; 120 if (node == null) { 121 return null; 122 } else { 123 if (node.getLeft() == NIL || node.getRight() == NIL) { 124 temp = node; 125 } else { 126 temp = successor(node); 127 } 128 129 if (temp.getLeft() != NIL) { 130 child = temp.getLeft(); 131 } else { 132 child = temp.getRight(); 133 } 134 135 child.setParent(temp.getParent()); 136 137 if (temp.getParent() == NIL) { 138 root = child; 139 } else if (temp == temp.getParent().getLeft()) { 140 temp.getParent().setLeft(child); 141 } else { 142 temp.getParent().setRight(child); 143 } 144 145 if (temp != node) { 146 node.setValue(temp.getValue()); 147 } 148 149 if (temp.getColor() == Color.BLACK) { 150 rb_Delete_Fixup(child); 151 } 152 return temp; 153 } 154 155 156 157 158 } 159 160 //删除节点后的调整 161 private void rb_Delete_Fixup(Node node) { 162 163 while (node != root && node.getColor() == Color.BLACK) { 164 165 if (node == node.getParent().getLeft()) { 166 167 Node rightBrother = node.getParent().getRight(); 168 if (rightBrother.getColor() == Color.RED) { //case 1 node节点为左孩子,node节点的兄弟为RED 169 rightBrother.setColor(Color.BLACK); 170 node.getParent().setColor(Color.RED); 171 leftRotate(node.getParent()); 172 rightBrother = node.getParent().getRight(); 173 } 174 175 if (rightBrother.getLeft().getColor() == Color.BLACK && rightBrother.getRight().getColor() == Color.BLACK) { 176 rightBrother.setColor(Color.RED); 177 node = node.getParent(); 178 } else if (rightBrother.getRight().getColor() == Color.BLACK) { 179 rightBrother.getLeft().setColor(Color.BLACK); 180 rightBrother.setColor(Color.RED); 181 rightRotate(rightBrother); 182 rightBrother = node.getParent().getRight(); 183 } else { 184 rightBrother.setColor(node.getParent().getColor()); 185 node.getParent().setColor(Color.BLACK); 186 rightBrother.getRight().setColor(Color.BLACK); 187 leftRotate(node.getParent()); 188 node = root; 189 } 190 191 192 } else { 193 194 Node leftBrother = node.getParent().getLeft(); 195 if (leftBrother.getColor() == Color.RED) { 196 leftBrother.setColor(Color.BLACK); 197 node.getParent().setColor(Color.RED); 198 rightRotate(node.getParent()); 199 leftBrother = node.getParent().getLeft(); 200 } 201 202 if (leftBrother.getLeft().getColor() == Color.BLACK && leftBrother.getRight().getColor() == Color.BLACK) { 203 leftBrother.setColor(Color.RED); 204 node = node.getParent(); 205 206 } else if (leftBrother.getLeft().getColor() == Color.BLACK) { 207 208 leftBrother.setColor(Color.RED); 209 leftBrother.getRight().setColor(Color.BLACK); 210 leftRotate(leftBrother); 211 leftBrother = node.getParent().getLeft(); 212 213 } else { 214 215 leftBrother.setColor(node.getParent().getColor()); 216 node.getParent().setColor(Color.BLACK); 217 leftBrother.getLeft().setColor(Color.BLACK); 218 rightRotate(node.getParent()); 219 node = root; 220 221 } 222 223 } 224 225 } 226 227 node.setColor(Color.BLACK); 228 } 229 230 231 //查找节点node的后继节点 232 233 public Node successor(Node node) { 234 235 Node rightChild = node.getRight(); 236 if (rightChild != NIL) { 237 Node previous = null; 238 while (rightChild != NIL) { 239 previous = rightChild; 240 rightChild = rightChild.getLeft(); 241 } 242 return previous; 243 } else { 244 245 Node parent = node.getParent(); 246 while (parent != NIL && node != parent.getLeft()) { 247 node = parent; 248 parent = parent.getParent(); 249 } 250 251 return parent; 252 253 } 254 255 } 256 257 258 //查找节点 259 public Node search(int data) { 260 Node temp = root; 261 262 while (temp != NIL) { 263 if (temp.getValue() == data) { 264 return temp; 265 } else if (data < temp.getValue()) { 266 temp = temp.getLeft(); 267 } else { 268 temp = temp.getRight(); 269 } 270 } 271 return null; 272 } 273 274 275 276 277 //左转函数 278 private void leftRotate(Node node) { 279 280 Node rightNode = node.getRight(); 281 282 node.setRight(rightNode.getLeft()); 283 if (rightNode.getLeft() != NIL) { 284 rightNode.getLeft().setParent(node); 285 } 286 rightNode.setParent(node.getParent()); 287 288 if (node.getParent() == NIL) { 289 rightNode = root; 290 } else if (node == node.getParent().getLeft()) { 291 node.getParent().setLeft(rightNode); 292 } else { 293 node.getParent().setRight(rightNode); 294 } 295 296 rightNode.setLeft(node); 297 node.setParent(rightNode); 298 299 300 } 301 302 //右转函数 303 private void rightRotate(Node node) { 304 305 Node leftNode = node.getLeft(); 306 node.setLeft(leftNode.getRight()); 307 308 if (leftNode.getRight() != null) { 309 leftNode.getRight().setParent(node); 310 } 311 312 leftNode.setParent(node.getParent()); 313 314 if (node.getParent() == NIL) { 315 root = leftNode; 316 } else if (node == node.getParent().getLeft()) { 317 node.getParent().setLeft(leftNode); 318 } else { 319 node.getParent().setRight(leftNode); 320 } 321 322 leftNode.setRight(node); 323 node.setParent(leftNode); 324 325 } 326 327 //中序遍历红黑树 328 public void printTree() { 329 inOrderTraverse(root); 330 } 331 332 private void inOrderTraverse(Node node) { 333 334 if (node != NIL) { 335 inOrderTraverse(node.getLeft()); 336 System.out.println(" 节点:"+node.getValue() + "的颜色为:" + node.getColor()); 337 inOrderTraverse(node.getRight()); 338 } 339 340 } 341 342 343 public Node getNIL() { 344 return NIL; 345 } 346 347 } 348 349 350 351 class Node { 352 private Node left; 353 private Node right; 354 private Node parent; 355 private Color color; 356 private int value; 357 358 public Node() { 359 } 360 361 public Node(Node left, Node right, Node parent, Color color, int value) { 362 super(); 363 this.left = left; 364 this.right = right; 365 this.parent = parent; 366 this.color = color; 367 this.value = value; 368 } 369 370 public Node(int value) { 371 this(null,null,null,null,value); 372 } 373 374 public Node getLeft() { 375 return left; 376 } 377 378 public void setLeft(Node left) { 379 this.left = left; 380 } 381 382 public Node getRight() { 383 return right; 384 } 385 386 public void setRight(Node right) { 387 this.right = right; 388 } 389 390 public Node getParent() { 391 return parent; 392 } 393 394 public void setParent(Node parent) { 395 this.parent = parent; 396 } 397 398 public Color getColor() { 399 return color; 400 } 401 402 public void setColor(Color color) { 403 this.color = color; 404 } 405 406 public int getValue() { 407 return value; 408 } 409 410 public void setValue(int value) { 411 this.value = value; 412 } 413 414 } 415 enum Color { 416 RED,BLACK 417 }
红黑树的动态演示:
http://www.cnblogs.com/yangecnu/p/Introduce-Red-Black-Tree.html