红黑树C++实现
1 /*
2 * rbtree.h
3 * 1. 每个节点是红色或者黑色
4 * 2. 根节点是黑色
5 * 3. 每个叶子节点是黑色(该叶子节点就空的节点)
6 * 4. 如果一个节点是红色,则它的两个子节点是黑色的
7 * 5.对每个节点,从该节点道其他所有后代的叶子节点的简单路径上,均包含相同数目的黑色节点
8 *
9 */
10
11 #ifndef SRC_RBTREE_H_
12 #define SRC_RBTREE_H_
13 #include<iostream>
14 #include<queue>
15
16 using namespace std;
17 enum colors{ RED,BLACK};
18 typedef int color_type;
19 namespace red_black_tree{
20 struct rb_tree_base{
21 struct rb_tree_base * parent;
22 struct rb_tree_base * left;
23 struct rb_tree_base * right;
24 color_type color;
25 };
26
27 template<class T>
28 struct rb_tree_node:public rb_tree_base{
29 T data;
30 typedef rb_tree_node<T>* link_type;
31 };
32 template<class Value>
33 class rb_tree{
34 public:
35 typedef rb_tree_base* rb_ptr;
36 typedef typename rb_tree_node<Value>::link_type link_type;
37 typedef rb_tree_node<Value> tree_node;
38 private:
39 rb_ptr head;
40 private:
41 bool _right_rotate(rb_ptr root);
42 bool _left_rotate(rb_ptr root);
43 rb_ptr _get_node(const Value& e) const;
44 bool _insert_fix_up(rb_ptr current_ptr);
45
46 bool _erase_fix_up(rb_ptr current_ptr,rb_ptr parent_ptr);
47
48 void _preOrder(rb_ptr root) const;
49
50 rb_ptr _successor(rb_ptr current_ptr) const;
51 public:
52 rb_tree();
53 ~rb_tree();
54 bool insert(const Value &e);
55 bool empty() const;
56 bool erase(const Value &e);
57 rb_ptr find(const Value &e);
58 void levelOrder() const;
59 void preOrder() const;
60 };
61 template<class Value>
62 rb_tree<Value>::rb_tree() {
63 head = new tree_node();
64 head->left=head;
65 head->right=head;
66 head->parent=head;
67
68 head->color=BLACK;
69 }
70
71 template<class Value>
72 rb_tree<Value>::~rb_tree() {
73 }
74
75 template<class Value>
76 bool rb_tree<Value>::insert(const Value& e) {
77 rb_ptr insert_ptr =_get_node(e);
78 if(head->parent ==head){
79 head->parent=insert_ptr;
80 insert_ptr->parent=head;
81 insert_ptr->color=BLACK;
82 return true;
83 }
84 rb_ptr root_ptr=head->parent;
85 rb_ptr root_remember=nullptr;
86 while(root_ptr){
87 root_remember=root_ptr;
88 if(link_type(insert_ptr)->data<=link_type(root_ptr)->data)
89 root_ptr=root_ptr->left;
90 else
91 root_ptr=root_ptr->right;
92 }
93 insert_ptr->parent=root_remember;
94 if(link_type(insert_ptr)->data <= link_type(root_remember)->data )
95 root_remember->left=insert_ptr;
96 else if(link_type(insert_ptr)->data >link_type( root_remember)->data)
97 root_remember->right=insert_ptr;
98 bool ret =_insert_fix_up(insert_ptr);
99 return ret;
100 }
101 template<class Value>
102 bool rb_tree<Value>::empty() const {
103
104 return head->parent==head;
105 }
106
107 template<class Value>
108 bool rb_tree<Value>::erase(const Value& e) {
109
110 rb_ptr erase_ptr = find(e);
111
112 if(!erase_ptr)
113
114 return false;
115
116 int erase_color =erase_ptr->color;
117
118 rb_ptr fix_up_ptr=nullptr;
119
120 rb_ptr fix_up_parent_ptr=nullptr;
121
122 if(erase_ptr){
123
124 if(!erase_ptr->left&&!erase_ptr->right){//叶子节点
125
126 if(erase_ptr==erase_ptr->parent->left){
127
128 erase_ptr->parent->left=nullptr;
129
130 fix_up_parent_ptr= erase_ptr->parent;
131
132 }
133
134 if(erase_ptr==erase_ptr->parent->right){
135
136 erase_ptr->parent->right=nullptr;
137
138 fix_up_parent_ptr= erase_ptr->parent;
139
140 }
141
142 if(erase_ptr==head->parent){
143
144 head->parent=head;
145
146 fix_up_parent_ptr=head;
147
148 }
149
150 erase_color =erase_ptr->color;
151
152 delete erase_ptr;
153
154 }else if(erase_ptr->right){
155
156 rb_ptr successor_ptr =_successor(erase_ptr);//left一定为空
157
158 link_type(erase_ptr)->data=link_type(successor_ptr)->data;
159
160 if(successor_ptr==successor_ptr->parent->left)
161
162 successor_ptr->parent->left=successor_ptr->right;
163
164 if(successor_ptr==successor_ptr->parent->right)
165
166 successor_ptr->parent->right=successor_ptr->right;
167
168 if(successor_ptr->right)
169
170 successor_ptr->right->parent=successor_ptr->parent;
171
172
173
174 fix_up_ptr=successor_ptr->right;
175
176 fix_up_parent_ptr=successor_ptr->parent;
177
178 erase_color=successor_ptr->color;
179
180 delete successor_ptr;
181
182 }else{//直接用左子树代替,或者找到后继节点代替也行,但比较麻烦,效果一样。
183
184 if(erase_ptr ==erase_ptr->parent->left)
185
186 erase_ptr->parent->left=erase_ptr->left;
187
188 else
189
190 erase_ptr->parent->right=erase_ptr->left;
191
192 erase_ptr->left->parent=erase_ptr->parent;
193
194 fix_up_ptr=erase_ptr->left;
195
196 fix_up_parent_ptr=erase_ptr->parent;
197
198 erase_color=erase_ptr->color;
199
200 delete erase_ptr;
201
202 }
203
204 if(erase_color==BLACK)
205
206 return _erase_fix_up(fix_up_ptr,fix_up_parent_ptr);
207
208 }
209 return false;
210 }
211
212 template<class Value>
213 typename rb_tree<Value>::rb_ptr rb_tree<Value>::find(const Value& e) {
214
215 rb_ptr root=head->parent;
216
217 if(head->parent !=head){
218
219 while(root){
220
221 if(link_type(root)->data == e)
222
223 return root;
224
225 else if( e<=link_type(root)->data){
226
227 root=root->left;
228
229 }else
230
231 root=root->right;
232
233 }
234
235 }
236 return nullptr;
237 }
238 /**
239 * current_ptr节点的祖父节点一定是黑色,因为它的父节点是红色的,所以性质4只在插入节点和该父节点被破坏
240 * 情况1:叔节节点uncle_ptr是红色;
241 * 1)父节点parent_ptr和叔节点uncle_ptr的颜色改为黑色,祖父节点grandfather_ptr的颜色改为红色
242 * 2)把current_ptr节点设置为grandfather,因为只有祖父节点和祖父节点的父节点之间会违法性质。
243
244 * 情况2:叔父节点uncle_ptr是黑色,或者unclue_ptr为空;
245
246 * 1)根据根据当前节点的位置,把当前节点current_ptr设置为parent_ptr,对其左旋或右旋。
247
248 * 情况3:叔父节点存在或者叔父节点颜色为黑色,且父右儿右关系(或父左儿左)
249
250 1)把父节点颜色设为黑色,把祖父颜色设为红色
251
252 2)对祖父节点进行左旋(或右旋)
253 *
254 */
255 template<class Value>
256 bool rb_tree<Value>:: _insert_fix_up(rb_ptr current_ptr){
257 while(current_ptr->parent->color ==RED){
258
259 rb_ptr parent_ptr =current_ptr->parent;
260 rb_ptr grandfather_ptr=parent_ptr->parent;
261 if(parent_ptr ==grandfather_ptr->left){
262 rb_ptr uncle_ptr=parent_ptr->parent->right;
263 if(uncle_ptr && uncle_ptr->color==RED){
264 parent_ptr->color=BLACK;
265 uncle_ptr->color=BLACK;
266 grandfather_ptr->color=RED;
267 current_ptr=grandfather_ptr;
268 }else if(current_ptr ==parent_ptr->right){
269 current_ptr=parent_ptr;
270 _left_rotate(current_ptr);
271 }else{
272
273 current_ptr->parent->color=BLACK;
274 current_ptr->parent->parent->color=RED;
275 _right_rotate(current_ptr->parent->parent);
276
277 }
278 }else{
279 rb_ptr uncle_ptr=parent_ptr->parent->left;
280 if(uncle_ptr && uncle_ptr->color==RED){
281 parent_ptr->color=BLACK;
282 uncle_ptr->color=BLACK;
283 grandfather_ptr->color=RED;
284 current_ptr=grandfather_ptr;
285 }else if(current_ptr ==parent_ptr->left){//uncle_ptr->color 是BLACK,或者uncle_ptr为空
286 current_ptr=parent_ptr;
287 _right_rotate(current_ptr);//其实就是转换为父右儿右的情况
288 }else{//父右儿右
289
290 current_ptr->parent->color=BLACK;
291 current_ptr->parent->parent->color=RED;
292 _left_rotate(current_ptr->parent->parent);
293
294 }
295 }
296 }
297 head->parent->color=BLACK;
298 return true;
299 }
300
301 template<class Value>
302
303 bool rb_tree<Value>::_erase_fix_up(rb_ptr current_ptr,rb_ptr parent_ptr){
304
305 while((!current_ptr||current_ptr->color==BLACK)&¤t_ptr!=head->parent){
306
307 if(parent_ptr->left ==current_ptr){
308
309 rb_ptr brother_ptr = parent_ptr->right;
310
311 if(brother_ptr->color ==RED){
312
313 parent_ptr->color=RED;
314
315 brother_ptr->color=BLACK;
316
317 _left_rotate(brother_ptr);
318
319 brother_ptr=current_ptr->parent->right;
320
321 }
322
323 if(brother_ptr->color==BLACK &&
324
325 (!brother_ptr->left ||brother_ptr->left->color ==BLACK)&&
326
327 (!brother_ptr->right || brother_ptr->right->color ==BLACK)){
328
329 brother_ptr->color=RED;
330
331 current_ptr=parent_ptr;
332
333 parent_ptr=current_ptr->parent;
334
335 }else {
336
337 if(brother_ptr->color==BLACK &&
338
339 (!brother_ptr->right||brother_ptr->right->color==BLACK)){//右侄黑,左侄红
340
341
342
343 brother_ptr->left->color=BLACK;
344
345 brother_ptr->color=RED;
346
347 _right_rotate(brother_ptr);
348
349 brother_ptr=parent_ptr->right;
350
351 }//右侄红色
352
353 brother_ptr->color=parent_ptr->color;
354
355 parent_ptr->color=BLACK;
356
357 if(brother_ptr->right)
358
359 brother_ptr->right->color=BLACK;
360
361 _left_rotate(parent_ptr);
362
363 current_ptr=head->parent;
364
365 }
366
367 }else{
368
369 rb_ptr brother_ptr = parent_ptr->left;
370
371 if(brother_ptr->color ==RED){
372
373 parent_ptr->color=RED;
374
375 brother_ptr->color=BLACK;
376
377 _right_rotate(brother_ptr);
378
379 brother_ptr=current_ptr->parent->left;
380
381 }
382
383 if(brother_ptr->color==BLACK &&
384
385 (!brother_ptr->left ||brother_ptr->left->color ==BLACK)&&
386
387 (!brother_ptr->right || brother_ptr->right->color ==BLACK)){
388
389 brother_ptr->color=RED;
390
391 current_ptr=parent_ptr;
392
393 parent_ptr=current_ptr->parent;
394
395 }else {
396
397 if(brother_ptr->color==BLACK &&
398
399 (!brother_ptr->right||brother_ptr->right->color==BLACK)){//右侄黑,左侄红
400
401 brother_ptr->left->color=BLACK;
402
403 brother_ptr->color=RED;
404
405 _left_rotate(brother_ptr);
406
407 brother_ptr=parent_ptr->left;
408
409 }//右侄红色
410
411 brother_ptr->color=parent_ptr->color;
412
413 parent_ptr->color=BLACK;
414
415 if(brother_ptr->left)
416
417 brother_ptr->left->color=BLACK;
418
419 _right_rotate(parent_ptr);
420
421 current_ptr=head->parent;
422
423 }
424
425 }
426
427 }
428
429 if (current_ptr)
430
431 current_ptr->color=BLACK;
432
433 return true;
434
435 }
436
437 template<class Value>
438
439 typename rb_tree<Value>::rb_ptr rb_tree<Value>::_successor(rb_ptr current_ptr) const{
440
441 rb_ptr right_child_ptr = current_ptr->right;
442
443 if(right_child_ptr){
444
445 rb_ptr left_ptr =right_child_ptr->left;
446
447 rb_ptr left_remember_ptr;
448
449 if(left_ptr){
450
451 while(left_ptr){
452
453 left_remember_ptr =left_ptr;
454
455 left_ptr=left_ptr->left;
456
457 }
458
459 return left_remember_ptr;
460
461 }
462
463 return right_child_ptr;
464
465
466
467 }else{
468
469 rb_ptr parent_ptr=current_ptr->parent;
470
471 while(current_ptr ==parent_ptr->right){
472
473 current_ptr=parent_ptr;
474
475 parent_ptr=parent_ptr->parent;
476
477 }
478
479 return parent_ptr;
480
481 }
482
483 return nullptr;
484
485 }
486 template<class Value>
487 typename rb_tree<Value>::rb_ptr rb_tree<Value>::_get_node(const Value& e) const {
488 rb_ptr insert_ptr = new tree_node();
489 link_type(insert_ptr)->data=e;
490 insert_ptr->parent=nullptr;
491 insert_ptr->left=nullptr;
492 insert_ptr->right=nullptr;
493 insert_ptr->color=RED;
494 return insert_ptr;
495 }
496 template<class Value>
497 bool rb_tree<Value>::_right_rotate(rb_ptr root){
498 if(root->left!=nullptr){
499 rb_ptr left_child_ptr=root->left;
500
501 root->left=left_child_ptr->right;
502 if(left_child_ptr->right !=nullptr)
503 left_child_ptr->right->parent=root;
504
505 left_child_ptr->right=root;
506 left_child_ptr->parent=root->parent;
507 if(root->parent->left ==root)
508 root->parent->left=left_child_ptr;
509 else if(root->parent->right==root)
510 root->parent->right=left_child_ptr;
511
512 if(root->parent==head){
513
514 root->parent->parent=left_child_ptr;
515
516 }
517
518 root->parent=left_child_ptr;
519 return true;
520 }
521 return false;
522 }
523 template<class Value>
524 bool rb_tree< Value >::_left_rotate(rb_ptr root){
525 if(root->right!=nullptr){
526 rb_ptr right_child_ptr=root->right;
527
528 root->right=right_child_ptr->left;
529 if(right_child_ptr->left != nullptr)
530 right_child_ptr->left->parent=root;
531
532 right_child_ptr->left=root;
533 right_child_ptr->parent=root->parent;
534 if(root->parent->left ==root)
535 root->parent->left=right_child_ptr;
536 else if(root->parent->right ==root)
537 root->parent->right=right_child_ptr;
538
539 if(root->parent==head){
540
541 root->parent->parent=right_child_ptr;
542
543 }
544 root->parent=right_child_ptr;
545
546 return true;
547 }
548 return false;
549 }
550 template<class Value>
551 void rb_tree<Value>::levelOrder() const {
552 rb_ptr root =head->parent;
553 queue<rb_ptr> q;
554 if(head->parent !=head){
555 q.push(root);
556 while(!q.empty()){
557 rb_ptr visit_ptr = q.front();
558 cout<<"data: "<<link_type(visit_ptr)->data<<" color: "<<((visit_ptr->color==0)?"RED":"BLACK")<<endl;
559 if(visit_ptr->left)
560 q.push(visit_ptr->left);
561 if(visit_ptr->right)
562 q.push(visit_ptr->right);
563 q.pop();
564 }
565 }
566 }
567 template<class Value>
568 void rb_tree<Value>:: _preOrder(rb_ptr root) const{
569 if(root){
570 cout<<"data: "<<link_type(root)->data<<" color: "
571
572 <<((root->color==0)?"RED":"BLACK")<<endl;
573 _preOrder(root->left);
574 _preOrder(root->right);
575 }
576 }
577 template<class Value>
578 void rb_tree<Value>:: preOrder() const{
579 _preOrder(head->parent);
580 }
581 }
582
583
584 //#include "rbtree.cpp"
585 #endif /* SRC_RBTREE_H_ */
红黑树C++实现的更多相关文章
- 红黑树——算法导论(15)
1. 什么是红黑树 (1) 简介 上一篇我们介绍了基本动态集合操作时间复杂度均为O(h)的二叉搜索树.但遗憾的是,只有当二叉搜索树高度较低时,这些集合操作才会较快:即当树的高度较高(甚至一种极 ...
- jdk源码分析红黑树——插入篇
红黑树是自平衡的排序树,自平衡的优点是减少遍历的节点,所以效率会高.如果是非平衡的二叉树,当顺序或逆序插入的时候,查找动作很可能会遍历n个节点 红黑树的规则很容易理解,但是维护这个规则难. 一.规则 ...
- 谈c++ pb_ds库(二) 红黑树大法好
厉害了,没想到翻翻pb_ds库看到这么多好东西,封装好的.现成的splay.红黑树.avl... 即使不能在考场上使用也可以用来对拍哦 声明/头文件 #include <ext/pb_ds/tr ...
- 定时器管理:nginx的红黑树和libevent的堆
libevent 发生超时后, while循环一次从堆顶del timer——直到最新调整的最小堆顶不是超时事件为止,(实际是del event),但是会稍后把这个timeout的 event放到ac ...
- 从2-3-4树到红黑树(下) Java与C的实现
欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 相关博客: 从2-3-4树到红黑树(上) 从2-3-4树到红黑树(中) 1. 实现技 ...
- 红黑树/B+树/AVL树
RB Tree 红黑树 :http://blog.csdn.net/very_2/article/details/5722682 Nginx的RBTree实现 :http://blog.csdn ...
- 论AVL树与红黑树
首先讲解一下AVL树: 例如,我们要输入这样一串数字,10,9,8,7,15,20这样一串数字来建立AVL树 1,首先输入10,得到一个根结点10 2,然后输入9, 得到10这个根结点一个左孩子结点9 ...
- DataStructure——红黑树学习笔记
1.前言 本文伪码和解释参考: http://blog.csdn.net/v_JULY_v/article/details/6105630 C实现的源码本文未贴出,请见: http://blog.cs ...
- 红黑树(Red-Black tree)
红黑树又称红-黑二叉树,它首先是一颗二叉树,它具体二叉树所有的特性.同时红黑树更是一颗自平衡的排序二叉树.我们知道一颗基本的二叉树他们都需要满足一个基本性质–即树中的任何节点的值大于它的左子节点,且小 ...
- map,hash_map, hash_table, 红黑树 的原理和使用
在刷算法题的时候总是碰到好多题,号称可以用hash table来解题.然后就蒙圈了. 1.首先,map和hash_map的区别和使用: (1)map底层用红黑树实现,hash_map底层用hash_t ...
随机推荐
- easyui datebox 扩展清空按钮
/** * 给时间框控件扩展一个清除的按钮 */ $.fn.datebox.defaults.cleanText = '清空'; (function ($) { var buttons = $.ext ...
- CSS3使用盒模型实现三栏布局
本篇文章由:http://xinpure.com/css3-box-model-to-implement-a-three-column-layout/ 使用 Position 绝对定位也是可以实现三栏 ...
- 【原创】说说JSON和JSONP,也许你会豁然开朗,含jQuery用例
说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义字符串或者用XML来描述,跨域可以通过服 ...
- MVC中Area的另一种用法
[摘要]本文只是为一行代码而分享 context.MapRoute("API", "api/{controller}/{action}", new { }, n ...
- tomcat 工作原理简析
https://github.com/HappyTomas/another-tutorial-about-java-web/blob/master/00-08.md 在00-02.理解HTTP中给出了 ...
- zookeeper(一):功能和原理
简介 ZooKeeper 是一个开源的分布式协调服务,由雅虎创建,是 Google Chubby 的开源实现.分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅.负载均衡.命名服务.分 ...
- Unity3D碰撞器事件测试(Rigidbody/Kinematic/Trigger/Collider)
1.Kinematic和刚体之间的碰撞事件 Unity官方有一个详细的碰撞关系表:http://docs.unity3d.com/Manual/CollidersOverview.html 但其实可以 ...
- poj 2846 Repository
题目大意:给你n个字符串,然后给你m个子串,看这个子串在上面的多少个串中,出现过: 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2846 本题可以在字 ...
- 关于引脚复用,不得不提的GPIO_Pin_sources 和GPIO_Pin
今天在端口复用时遇到了困惑,参考:http://www.51hei.com/bbs/dpj-40992-1.html 调整前的代码GPIO_PinAFConfig(GPIOA,GPIO_Pin_9,G ...
- SysTick—系统定时器
本章参考资料<ARM Cortex™-M4F 技术参考手册> -4.5 章节 SysTick Timer(STK), 和4.48 章节 SHPRx,其中 STK 这个章节有 SysTick ...