红黑树

  1 import java.util.Random;
  2 
  3 
  4 public class RBTree 
  5 {
  6     
  7     private Node root;
  8     
  9     
 10     public RBTree(int[] array)
 11     {
 12         for (int i : array) insert(i);
 13     }
 14     
 15     private Node search(int key, Node node)
 16     {
 17         if (node == null) return null;
 18         int compare = compare(key, node.key);
 19         
 20         if (compare == 0) return node;
 21         if (compare > 0) 
 22             return search(key, node.right);
 23         else 
 24             return search (key, node.left);
 25     }
 26     
 27     /*
 28      * 插入节点
 29      */
 30     public boolean insert(int key)
 31     {
 32         Node node = new Node(key);
 33         node.color = 'R';
 34         
 35         Node parent = null, current = root;
 36         int compare = 0;
 37         
 38         /*
 39          * 寻找插入节点的父节点
 40          */
 41         while (current != null) {
 42             parent = current;
 43             compare = compare(key, current.key);
 44                 
 45             if (compare == 0) return false;
 46             
 47             if (compare == 1)
 48                 current = current.right;
 49             else
 50                 current = current.left;
 51         }
 52 
 53         // 添加新节点
 54         if (parent == null) {
 55             root = node;
 56         }
 57         else {
 58             node.parent = parent;
 59             if (compare == 1) {
 60                 parent.right = node;
 61             }
 62             else { 
 63                 parent.left = node;
 64             }
 65         }
 66         
 67         insertFixup(node);
 68         return true;
 69     }
 70     
 71     private void insertFixup(Node node)
 72     {
 73         while (node != root && node.parent.color == 'R') {
 74             // 父节点为祖父节点的左节点
 75             if (node.parent == node.parent.parent.left) {
 76                 Node uncle = node.parent.parent.right;
 77                 /*
 78                  * 父节点与叔叔节点都是红色
 79                  * 将父节点与叔叔节点变成黑色
 80                  * 将祖父节点变成红色
 81                  * 当前节点指向组父节点 
 82                  */
 83                 if (uncle != null && uncle.color == 'R') {
 84                     node.parent.color = 'B';
 85                     uncle.color = 'B';
 86                     uncle.parent.color = 'R';
 87                     node = node.parent.parent;
 88                 }
 89                 else {
 90                     /*
 91                      * 叔叔节点是黑色且node为右孩子
 92                      * 当前结点指向父节点
 93                      * 以当前结点为中心左旋
 94                      */
 95                     if (node == node.parent.right) {
 96                         node = node.parent;
 97                         leftRotate(node);
 98                     }
 99                     
100                     /*
101                      * 叔叔节点是黑色且node为左孩子
102                      * 父节点变为黑色,组父节点变为红色
103                      * 以祖父节点为中心右旋
104                      */
105                     node.parent.color = 'B';
106                     node.parent.parent.color = 'R';
107                     rightRotate(node.parent.parent);
108                 }
109             }
110             else {
111             // 父节点为祖父节点的右节点
112                 Node uncle = node.parent.parent.left;
113                 
114                 // 操作与上面相反
115                 if (uncle != null && uncle.color == 'R') {
116                     node.parent.color = 'B';
117                     uncle.color = 'B';
118                     uncle.parent.color = 'R';
119                     node = node.parent.parent;
120                 }
121                 else {
122                     if (node == node.parent.left) {
123                         node = node.parent;
124                         rightRotate(node);
125                     }
126                     node.parent.color = 'B';
127                     node.parent.parent.color = 'R';
128                     leftRotate(node.parent.parent);
129                 }
130             }
131         }
132         root.color = 'B';
133     }
134     
135     private void deleteFixup(Node node)
136     {
137         if (node == null) return;
138         
139         while (node != root && node.color == 'B') {
140             // node为父节点的左子节点
141             if (node == node.parent.left) {
142                 Node sibling = node.parent.right;
143                 
144                 /*
145                  * 当前结点为黑色且兄弟节点为红色
146                  * 将父节点染成红色,兄弟节点染成黑色
147                  * 针对父节点最一次左旋
148                  */
149                 if (sibling.color == 'R') {
150                     sibling.color = 'B';
151                     sibling.parent.color = 'R';
152                     leftRotate(node.parent);
153                     sibling = node.parent.right;
154                 }
155                 
156                 /*
157                  * 当前结点和兄弟节点为黑色,兄弟节点的子节点都为黑色
158                  * 将当前节点和兄弟节点抽出一重黑色加到父节点上
159                  * 把父节点当成新的节点继续计算
160                  */
161                 if (sibling.left.color == 'B' 
162                     && sibling.right.color == 'B') 
163                 {
164                     sibling.color = 'R';
165                     node = node.parent;
166                 }
167                 else {
168                     /*
169                      * 当前节点和兄弟节点为黑色,兄弟的左子节点为红色
170                      * 把兄弟节点染红,兄弟左子节点染黑
171                      * 以兄弟节点位置点右旋
172                      */
173                     if (sibling.right.color == 'B') {
174                         sibling.left.color = 'B';
175                         sibling.color = 'R';
176                         rightRotate(sibling);
177                         sibling = node.parent.right;
178                     }
179                     
180                     /*
181                      * 当前结点和兄弟节点为黑色,兄弟右子节点为红色
182                      * 把兄弟节点染成当前结点的父节点的颜色
183                      * 将当前节点的父节点染成黑色
184                      * 兄弟节点有子节点染成黑色
185                      * 以当前节点的父节点为支点左旋
186                      */
187                     sibling.color = node.parent.color;
188                     node.parent.color = 'B';
189                     sibling.right.color = 'B';
190                     leftRotate(node.parent);
191                     node = root;
192                 }
193             }
194             // node为父节点的右子节点
195             else {
196                 Node sibling = node.parent.left;
197                 
198                 /*
199                  * 当前结点为黑色,兄弟节点为红色
200                  * 将兄弟节点染成黑色
201                  * 当前结点的父节点染成红色
202                  * 以当前节点的父节点进行右旋
203                  */
204                 if (sibling.color == 'R') {
205                     sibling.color = 'B';
206                     sibling.parent.color = 'R';
207                     rightRotate(node.parent);
208                     sibling = node.parent.left;
209                 }
210                 
211                 /*
212                  * 当前结点和兄弟节点为黑色
213                  * 把当前结点和兄弟节点抽取一重黑色到父节点上
214                  * 把当前节点当作新的节点重新计算
215                  */
216                 if (sibling.left.color == 'B' && sibling.right.color == 'B') {
217                     sibling.color = 'R';
218                     sibling.parent.color = 'B';
219                     node = node.parent;
220                 }
221                 else {
222                     /*
223                      * 当前结点和兄弟节点为黑色,兄弟的右子节点为红色
224                      * 把兄弟节点染红,兄弟的左子节点染黑
225                      * 以兄弟节点为支点左旋
226                      */
227                     if (sibling.left.color == 'B') {
228                         sibling.color = 'R';
229                         sibling.right.color = 'B';
230                         leftRotate(sibling);
231                         sibling = node.parent.left;
232                     }
233                     
234                     /*
235                      * 当前结点和兄弟节点为黑色,兄弟的右子节点为黑色
236                      * 将兄弟节点染成当前结点的父节点的颜色
237                      * 当前节点的父节点染黑
238                      * 以当前结点的父节点为支点进行右旋
239                      */
240                     sibling.color = node.parent.color;
241                     node.parent.color = 'B';
242                     sibling.left.color = 'B';
243                     rightRotate(node.parent);
244                     node = root;
245                 }
246             }
247         }
248         node.color = 'B';
249     }
250     
251     /*
252      * 删除节点
253      * 只会在只有一个子节点的节点上进行
254      */
255     public void delete(int key)
256     {
257         Node node = search(key, root);
258         if (node == null) return;
259         
260         Node delete, child = null;
261         
262         // 如果有两个子节点则删除是其节点后继节点
263         if (node.left == null || node.right == null) {
264             delete = node;
265         }
266         else {
267             delete = interval(node);
268         }
269         
270         // 如国有子节点则判断是那个子节点
271         if (delete.left != null || delete.right != null) {
272             if (delete.left != null)
273                 child = delete.left;
274             else
275                 child = delete.right;
276             
277             child.parent = delete.parent;
278         }
279         
280         // 清除删除节点的引用
281         if (delete.parent == null) {
282             root = child;
283         }
284         else {
285             if (delete == delete.parent.left)
286                 delete.parent.left = child;
287             else
288                 delete.parent.right = child;
289         }
290         
291         // 如果删除的是后继节点则将当前其值赋给当前结点
292         if (delete != node) {
293             node.key = delete.key;
294         }
295         
296         // 调整红黑树平衡
297         if (delete.color == 'B')
298             deleteFixup(child);
299     }
300     
301     private void leftRotate(Node node)
302     {
303         /*
304          * 左旋
305          *        P                  P
306          *       / \                / \
307          *      @   d              y   d
308          *     / \       -->      / \
309          *    a   y              @   c
310          *       / \            / \
311          *      b   c          a   b
312          */
313         
314         Node right = node.right;
315         node.right = right.left;
316         
317         if (node.right != null) {
318             node.right.parent = node;
319         }
320         
321         right.parent = node.parent;
322         if (right.parent == null) {
323             root = right;
324         }
325         else {
326             if (node == node.parent.left)
327                 node.parent.left = right;
328             else
329                 node.parent.right = right;
330         }
331         
332         right.left = node;
333         node.parent = right;
334     }    
335     
336     private void rightRotate(Node node)
337     {
338         /*
339          * 右旋
340          *        P                P
341          *       / \              / \
342          *      d   @            d   y
343          *         / \    -->       / \
344          *        y   a            b   @        
345          *       / \                  / \
346          *      b   c                c   a
347          */
348         
349         Node left = node.left;
350         node.left = left.right;
351         
352         if (node.left != null) {
353             node.left.parent = node;
354         }
355         
356         left.parent = node.parent;
357         if (left.parent == null) {
358             root = left;
359         }
360         else {
361             if (node == node.parent.left) 
362                 node.parent.left = left;
363             else 
364                 node.parent.right = left;
365         }
366         
367         left.right = node;
368         node.parent = left;
369     }
370 
371     /*
372      * 最小值想做遍历寻找
373      */
374     private Node min(Node node)
375     {
376         while (node.left != null) {
377             node = node.left;
378         }
379         return node;
380     }
381     
382     /*
383      * 最大值向右遍历寻找
384      */
385     private Node max(Node node)
386     {
387         while (node.right != null) {
388             node = node.right;
389         }
390         return node;
391     }
392     
393     /*
394      * 查找直接后继节点
395      */
396     private Node interval(Node node)
397     {
398         /*
399          * 如果有右子节点则在右子节点中寻找
400          * 否则查找父节点为左子节点的节点作为后继节点
401          */
402         if (node.right != null)
403             return min(node.right);
404         else {
405             Node parent = node.parent;
406             while (parent != null && node == parent.right) {
407                 node = parent;
408                 parent = node.parent;
409             }
410             return parent;
411         }
412     }
413     
414     /*
415      * 比较大小
416      */
417     private int compare(int a, int b)
418     {
419         return a > b ? 1 : a < b ? -1 : 0;
420     }
421 
422     /*
423      * 前序遍历
424      */
425     public void preOrder()
426     {
427         preOrder(root);
428     }
429     
430     private void preOrder(Node node)
431     {
432         if (node == null) return;
433         
434         System.out.println(node.key + " " + node.color);
435         preOrder(node.left);
436         preOrder(node.right);
437     }
438     
439     /*
440      * 后续遍历
441      */
442     public void postOrder()
443     {
444         postOrder(root);
445     }
446     
447     private void postOrder(Node node)
448     {
449         if (node == null) return;
450         
451         postOrder(node.left);
452         postOrder(node.right);
453         System.out.println(node.key + " " + node.color);
454     }
455     
456     /*
457      * 中序遍历
458      */
459     public void inOrder()
460     {
461         inOrder(root);
462     }
463     
464     private void inOrder(Node node)
465     {
466         if (node == null) return;
467         
468         inOrder(node.left);
469         System.out.println(node.key + " " + node.color);
470         inOrder(node.right);
471     }
472     
473     static class Node
474     {
475         Node parent;
476         Node left;
477         Node right;
478         char color = 'B';
479         int key;
480         
481         public Node(int key)
482         {
483             this.key = key;
484         }
485         
486         public Node(char color)
487         {
488             this.color = color;
489             this.key = -Integer.MIN_VALUE;
490         }
491     }
492     
493     public static void main(String[] args)
494     {
495         int[] array = new int[20];
496         
497         Random rond = new Random();
498         for (int i = 0; i < array.length; i++) {
499             array[i] = Math.abs(rond.nextInt()) % 40;
500         }
501         
502         RBTree tree = new RBTree(array);
503         //tree.preOrder();
504         tree.inOrder();
505         
506         System.out.println();
507         System.out.println("delete " + array[6]);
508         System.out.println();
509         
510         tree.delete(array[6]);
511         //tree.preOrder();
512         tree.inOrder();
513     }
514 }
原文地址:https://www.cnblogs.com/rilley/p/2586810.html