C++紅黑樹
阿新 • • 發佈:2017-11-02
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); 13RBTree.h}* 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 boolIsExist(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
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 testmain.cpp
C++紅黑樹