码迷,mamicode.com
首页 > 编程语言 > 详细

C++红黑树

时间:2017-11-02 21:58:34      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:释放内存   旋转   dom   存在   ret   front   左右   map   lis   

技术分享
 1 #ifndef _RBTREE_H_
 2 #define _RBTREE_H_
 3 
 4 const int nodeSize = 3;
 5 class RBTree
 6 {
 7 private:
 8     typedef struct Node {
 9         int key;
10         int color;    //0为红,1为黑
11         Node * family[nodeSize];    //family[0]左节点,family[1]右节点,family[2]父节点
12         Node(int k, int c);
13     }* Pnode;
14 private:
15     Pnode nil;
16     Pnode root;
17 private:
18     //返回k节点
19     Pnode __GetNode(int k);
20     //中序遍历
21     void __ShowNode(Pnode n)const;
22     //旋转节点,direction 为 0 左旋转,1右旋转
23     void __Rotate(Pnode n, int direction);
24     //修正插入后的红黑树
25     void __InsertFixup(Pnode n);
26     //修正删除后的红黑树
27     void __DeleteFixup(Pnode delNode);
28     //释放内存
29     void __Clear(Pnode n);
30     //返回当前节点(包含当前节点)下的所有节点个数.
31     size_t __NodeSize(Pnode n);
32     //返回节点n的前驱(direction = 0),后继(direction = 1)
33     Pnode __GetNeighbor(Pnode n, int direction);
34 public:
35     RBTree();
36     bool IsExist(int k);
37     size_t Size();
38     //按从小到大打印所有节点的key值
39     void ShowList()const;
40     //按树的层次打印节点的key值和颜色(R,B)
41     void ShowTree()const;
42     //插入新节点
43     void Insert(int k);
44     //删除节点
45     void Delete(int k);
46     ~RBTree();
47 };
48 
49 #endif
RBTree.h
技术分享
  1 #include "RBTree.h"
  2 #include <iostream>
  3 #include <queue>
  4 
  5 using namespace std;
  6 
  7 RBTree::Node::Node(int k = 0x80000000, int c = 0) :key(k), color(c), family{} {}
  8 
  9 RBTree::RBTree(): nil(new Node(0x80000000, 1)), root(nil){}
 10 
 11 RBTree::~RBTree() 
 12 {
 13     __Clear(root);
 14     delete nil;
 15 }
 16 
 17 void RBTree::__Clear(Pnode n)
 18 {
 19     if (n == nil)
 20         return;
 21     __Clear(n->family[0]);
 22     __Clear(n->family[1]);
 23     delete n;
 24 }
 25 
 26 bool RBTree::IsExist(int k) 
 27 {
 28     return __GetNode(k) != nil;
 29 }
 30 
 31 size_t RBTree::__NodeSize(Pnode n)
 32 {
 33     if (n == nil)
 34         return 0;
 35     return 1 + __NodeSize(n->family[0]) + __NodeSize(n->family[1]);
 36 }
 37 
 38 void RBTree::__ShowNode(Pnode n) const
 39 {
 40     if (n == nil)
 41         return;
 42     __ShowNode(n->family[0]);
 43     cout << n->key << " ";
 44     __ShowNode(n->family[1]);
 45 }
 46 
 47 void RBTree::ShowList() const
 48 {
 49     __ShowNode(root);
 50     cout << endl;
 51 }
 52 
 53 void RBTree::ShowTree() const
 54 {
 55     queue<Pnode> dn;
 56     if(root != nil)
 57         dn.push(root);
 58     int size = 0;
 59     while (!dn.empty())
 60     {
 61         size = dn.size();
 62         for (int i = 0; i < size; i++)
 63         {
 64             cout << dn.front()->key;
 65             if (dn.front()->color)
 66                 cout << "B  ";
 67             else cout << "R  ";
 68             if (dn.front()->family[0] != nil)
 69                 dn.push(dn.front()->family[0]);
 70             if (dn.front()->family[1] != nil)
 71                 dn.push(dn.front()->family[1]);
 72             dn.pop();
 73         }
 74         cout << endl;
 75     }
 76 }
 77 
 78 RBTree::Pnode RBTree::__GetNeighbor(Pnode n, int direction)
 79 {
 80     Pnode current{};
 81     if (n->family[direction] != nil)
 82     {
 83         current = n->family[direction];
 84         while (current->family[!direction] != nil)
 85             current = current->family[!direction];
 86     }
 87     else {
 88         current = n;
 89         while (current->family[2] != nil && current != current->family[2]->family[!direction])
 90             current = current->family[2];
 91         current = current->family[2];
 92     }
 93     return current;
 94 }
 95 
 96 RBTree::Pnode RBTree::__GetNode(int k)
 97 {
 98     Pnode current = root;
 99     while (current != nil)
100     {
101         if (current->key == k)
102             break;
103         else
104             current = current->family[k > current->key];
105     } 
106     return current;
107 }
108 
109 //direction = 0 左转,1 右转
110 void RBTree::__Rotate(Pnode x, int direction)
111 {
112     Pnode y = x->family[!direction];
113     x->family[!direction] = y->family[direction];
114     if (y->family[direction])
115         y->family[direction]->family[2] = x;
116     y->family[2] = x->family[2];
117     if (x->family[2] == nil)
118         root = y;
119     else
120         x->family[2]->family[x == x->family[2]->family[1]] = y;
121     x->family[2] = y;
122     y->family[direction] = x;
123 }
124 
125 void RBTree::__InsertFixup(Pnode n)
126 {
127     int plr = 0;
128     //如果n的父节点不为空,且父节点颜色为红色
129     while (!n->family[2]->color)
130     {
131         //如果n的父节点是祖父节点的左节点,则plr = 0,反之为1
132         plr = (n->family[2] == n->family[2]->family[2]->family[0] ? 0 : 1);
133         //如果存在叔节点,且叔节点颜色为红,则将父节点和叔结点颜色变黑,当前节点成为祖节点且颜色变红.
134         if ((n->family[2]->family[2]->family[!plr]) &&
135             !(n->family[2]->family[2]->family[!plr]->color))
136         {
137             n = n->family[2]->family[2];
138             n->color = 0;
139             n->family[plr]->color = 1;
140             n->family[!plr]->color = 1;
141         }
142         else {
143             //如果n是左节点,则lr为0,反之为1
144             int lr = n == n->family[2]->family[0] ? 0 : 1;
145             //如果n是左节点,其父为右节点;或者n是右节点,其父为左节点
146             if (lr + plr == 1)
147             {
148                 n = n->family[2];
149                 __Rotate(n, !lr);
150                 //旋转后,n变为原来反方向的节点
151                 lr = !lr;
152             }
153             n = n->family[2]->family[2];
154             __Rotate(n, !lr);
155             n->color = 0;
156             n->family[2]->color = 1;
157             break;        
158         }
159     }
160     root->color = 1;
161 }
162 
163 void RBTree::Insert(int k)
164 {
165     Pnode current = root;
166     Pnode prev = nil;
167     while (current != nil)
168     {
169         prev = current;
170         if (k < current->key)
171             current = current->family[0];
172         else if (k > current->key)
173             current = current->family[1];
174         else {
175             cout << k << " is already exist!!!\n";
176             return;
177         }
178     }
179     Pnode new_node = new Node(k);
180     new_node->family[0] = new_node->family[1] = nil;
181     new_node->family[2] = prev;
182     if (root == nil)
183         root = new_node;
184     else if (k < prev->key)
185         prev->family[0] = new_node;
186     else prev->family[1] = new_node;
187     __InsertFixup(new_node);
188 }
189 
190 
191 void RBTree::__DeleteFixup(Pnode delNode)
192 {
193     Pnode bakNode = delNode;
194     while (delNode != root && delNode->color)
195     {
196         //delNode如果是左孩子lr = 0, 反之lr = 1,为便于思考,假定lr=0,即delNode为左孩子.
197         int lr = delNode == delNode->family[2]->family[1];
198         Pnode brother = delNode->family[2]->family[!lr];
199         //如果兄弟结点颜色为红色,则其父结点和兄弟孩子的颜色必为黑,以父节点为轴左旋转重新着色后,delNode新兄弟结点颜色为黑
200         if (!brother->color) {
201             delNode->family[2]->color = 0;
202             brother->color = 1;
203             __Rotate(delNode->family[2], lr);
204             brother = delNode->family[2]->family[!lr];
205         }
206         //如果兄弟左右孩子都为黑色,兄弟结点着红色,将父结点成为当前节点
207         if (brother->family[0]->color && brother->family[1]->color) {
208             brother->color = 0;
209             delNode = delNode->family[2];
210         }
211         else {
212             //如果兄弟右孩子为黑色
213             if (brother->family[!lr]->color) {
214                 brother->color = 0;
215                 brother->family[lr]->color = 1;
216                 __Rotate(brother, !lr);
217                 brother = brother->family[2];
218             }
219             brother->color = brother->family[2]->color;
220             brother->family[!lr]->color = 1;
221             brother->family[2]->color = 1;
222             __Rotate(brother->family[2], lr);
223             break;
224         }
225     }
226     delNode->color = 1;
227     //删除节点,释放内存
228     if (bakNode == root)
229         root = nil;
230     else if (bakNode == bakNode->family[2]->family[0])
231         bakNode->family[2]->family[0] = nil;
232     else 
233         bakNode->family[2]->family[1] = nil;
234     delete bakNode;
235 }
236 
237 void RBTree::Delete(int k)
238 {
239     Pnode delNode = __GetNode(k);
240     if (delNode == nil) {
241         cout << k << "is not exist, delete failed!\n";
242         return;
243     }
244     //如果有双子节点,找后继节点successor,则successor没有左子节点
245     if(delNode->family[0] != nil && delNode->family[1] != nil)
246     {
247         Pnode successor = __GetNeighbor(delNode, 0);
248         delNode->key = successor->key;
249         delNode = successor;
250     }
251     //如果没子节点
252     if (delNode->family[0] == nil && delNode->family[1] == nil) {
253         __DeleteFixup(delNode);
254     }
255     //如果仅有单子节点,那么delNode必为黑色,且其独生子女为红色
256     else{
257         int lr = delNode->family[0] == nil;
258         delNode->key = delNode->family[lr]->key;
259         delete delNode->family[lr];
260         delNode->family[lr] = nil;
261     }
262 }
263 
264 size_t RBTree::Size()
265 {
266     return __NodeSize(root);
267 }
RBTee.cpp
技术分享
 1 #define CRTDBG_MAP_ALLOC    
 2 #include "stdafx.h"
 3 #include <crtdbg.h>    
 4 #include "RBTree.h"
 5 #include <iostream>
 6 #include <ctime>
 7 
 8 using namespace std;
 9 const int ASIZE = 10;
10 void LoadArrayToTree(RBTree & t, int * arr, int n);
11 void GetRandomArray(int * arr, int n);
12 void ShowArray(int * arr, int n);
13 void Show(RBTree & t);
14 void DeleteTree(RBTree &t, int * arr, int n);
15 
16 int main()
17 {
18     {
19         srand(size_t(time(0)));
20         int arr[ASIZE]{11,26,35,14,5,26,57,8,39,10};
21         //int arr[ASIZE]{};
22         //GetRandomArray(arr, ASIZE);
23         ShowArray(arr, ASIZE);
24         RBTree t;
25         LoadArrayToTree(t, arr, ASIZE);
26         Show(t);
27         DeleteTree(t, arr, ASIZE);
28         Show(t);
29     }
30     //内存泄露测试
31     _CrtDumpMemoryLeaks();
32     return 0;
33 }
34 
35 //main test method
36 void LoadArrayToTree(RBTree & t, int * arr, int n)
37 {
38     for (int i = 0; i < n; i++)
39         t.Insert(arr[i]);
40 }
41 
42 void DeleteTree(RBTree & t, int * arr, int n)
43 {
44     for (int i = 0; i < n; i++) 
45         t.Delete(arr[i]);        
46 }
47 
48 void GetRandomArray(int * arr, int n)
49 {
50     for (int i = 0; i < n; i++)
51     {
52         arr[i] = rand()%50000+1;
53         //不重复数组
54         /*int num = rand() % 50000 + 1;
55         int j = 0;
56         for (j = 0; j < i; j++)
57         {
58             if (arr[j] == num)
59                 break;
60         }
61         if (j == i)
62             arr[i] = num;
63         else --i;*/
64     }
65 }
66 
67 void ShowArray(int * arr, int n)
68 {
69     for (int i = 0; i < n; i++)
70         cout << arr[i] << " ";
71     cout << endl;
72 }
73 
74 void Show(RBTree & t)
75 {
76     cout << "\nt.Size() = " << t.Size() << endl;
77     cout << "********************List**********************\n";
78     t.ShowList();
79     cout << "********************Tree**********************\n";
80     t.ShowTree();
81     cout << "********************End***********************\n";
82     cout << endl;
83 }
84 // end of main test
main.cpp

 

C++红黑树

标签:释放内存   旋转   dom   存在   ret   front   左右   map   lis   

原文地址:http://www.cnblogs.com/endenvor/p/7774605.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!