数据结构——红黑树

红黑树也是一种平衡二叉查找树,经常用于替代AVL树,特点如下:

  1. 根节点为黑色的,空节点也看做黑色节点;
  2. 红色节点的子节点一定为黑色,任何一条路径不能出现两个连续的红节点
  3. 从任何一个节点出发,到空节点的路径上包含相同数目的黑节点,即如果忽略路径中的红色节点,红黑树是完全平衡的。

  相对于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 }
View Code

 红黑树的动态演示:

http://www.cnblogs.com/yangecnu/p/Introduce-Red-Black-Tree.html

posted @ 2016-07-28 10:56  TonyLuis  阅读(339)  评论(0)    收藏  举报