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 }

 

posted on 2020-10-13 19:33  二十二画生的执著  阅读(134)  评论(0编辑  收藏  举报