1. 程式人生 > >C++紅黑樹

C++紅黑樹

cpp insert none turn 後繼 cout spl list 結點

技術分享
 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++紅黑樹