为了让这片博客看起来更有营养一些,我还是在添加一些红黑树的设计原理吧?
Q:为什么要为叶节点加入终止节点NIL?
A:其实这个NIL的假如本省没有什么,但是当规定完NIL的颜色为Black时,他的作用就显现出来了,但他的颜色为Black时无论是Insert还是delete,都可以起到辅佐判断的作用例:
假如向上面这种情况,插入节点为C那么我们就可以通过判断其叔节点的颜色,也就是NIL的颜色把其对应于正确的case2中去。
不知道是我买的是盗版的原因还是本身书中就有这个问题《算法导论》中文翻译第三版的179页的关于RB-INSERT-FLXUP的操作中对于case3没有加else,这应该是错误的,应该是在case2后加上case3,然后再加上在else里写上case3。
下面是算法导论红黑树部分的代码实现,其中大部分代码是根据算法导论的二叉树的部分改编过来的,所以会看到一些有些过于单纯的二叉树操作还请见谅!
重点强调了红黑树的插入和删除部分的代码!!
这个代码还是写了不少的,但是为什么会有红黑树这种数据结构,换句话说通过导论引理13.1的证明,这中操作后能保证搜索二叉树的高度小于lg(n+1),但如果仅从这个角度产生的对于搜索的代价来看的话红黑树的优势显然不如AVL,那么为什么要用红黑树呢?
代码:
1 #include<iostream> 2 #include<stack> 3 4 using namespace std; 5 6 #define Red 1 7 #define Black 0 8 9 typedef struct node 10 { 11 int key; 12 node* left; 13 node* right; 14 node* parent; 15 int color; // 红黑树的节点颜色标识,选取Red-1,Black-0; 16 }Node; 17 18 int visited; 19 int colorFlag; 20 Node* NIL; 21 Node* Root; 22 23 // 创建二叉树,数据来控制台。按中序遍历的方式输入。 24 void CreatBinaryTree(Node &node) 25 { 26 cout << "输入" << node.key << "的左儿子" << endl; 27 int x; 28 cin >> x; 29 if (x != -1) 30 { 31 Node *lnode = new Node(); 32 lnode->key = x; 33 node.left = lnode; 34 lnode->parent = &node; 35 CreatBinaryTree(*lnode); 36 } 37 else 38 { 39 node.left = NULL; 40 } 41 cout << "输入" << node.key << "的右儿子" << endl; 42 int y; 43 cin >> y; 44 if (y != -1) 45 { 46 Node *rnode = new Node(); 47 rnode->key = y; 48 node.right = rnode; 49 rnode->parent = &node; 50 CreatBinaryTree(*rnode); 51 } 52 else 53 { 54 node.right = NULL; 55 } 56 } 57 58 // 按照中序访问建立二叉树,数组要求为先序遍历返回结果,且左儿子,右儿子为空设定起等于-1; 59 void CreateBinaryTreeByArray(Node *root, int a[]) 60 { 61 //输入root的key 62 root->key = a[visited]; 63 visited++; 64 if (a[visited] == -1) 65 { 66 root->left = NULL; 67 visited++; 68 } 69 else 70 { 71 root->left = new Node(); 72 root->left->parent = root; 73 CreateBinaryTreeByArray(root->left, a); 74 } 75 if (a[visited] == -1) 76 { 77 root->right = NULL; 78 visited++; 79 } 80 else 81 { 82 root->right = new Node(); 83 root->right->parent = root; 84 CreateBinaryTreeByArray(root->right, a); 85 } 86 } 87 88 // 递归法中序访问二叉树 89 void Traverse(Node *root) 90 { 91 if (root != NULL) 92 { 93 Traverse(root->left); 94 cout << root->key << " " << endl; 95 Traverse(root->right); 96 } 97 } 98 99 100 // 非递归借用栈迭代中序遍历二叉树。 101 void NonRecursionTraverse(Node *root) 102 { 103 stack<Node*> treeStack; 104 Node *p = root->left; 105 treeStack.push(root); 106 while (!(treeStack.empty() && p == NULL)) 107 { 108 while (p != NULL) 109 { 110 treeStack.push(p); 111 p = p->left; 112 } 113 Node *top = treeStack.top(); 114 cout << top->key << " "; 115 treeStack.pop(); 116 p = top->right; 117 } 118 } 119 120 121 // 递归二叉树搜索树的搜索 122 Node* TreeSearch(Node *root, int x) 123 { 124 if (root == NULL || x == root->key) 125 return root; 126 if (x < root->key) 127 return TreeSearch(root->left, x); 128 else 129 return TreeSearch(root->right, x); 130 } 131 132 133 // 非递归二叉搜索树的搜索 134 Node* InteractiveTreeSearch(Node* root, int x) 135 { 136 while (root != NULL && root->key != x) 137 { 138 if (x < root->key) 139 root = root->left; 140 else 141 root = root->right; 142 } 143 return root; 144 } 145 146 147 // 返回二叉搜索树中关键字最小的元素 148 Node *TreeMinimum(Node* root) 149 { 150 while (root->left != NULL) 151 root = root->left; 152 return root; 153 } 154 155 Node* RecursionTreeMinimun(Node* root) 156 { 157 if (root->left == NULL) 158 return root; 159 return RecursionTreeMinimun(root->left); 160 } 161 162 // 返回二叉搜索树中关键字最大的元素 163 Node *TreeMaxmum(Node* root) 164 { 165 while (root->right != NULL) 166 root = root->right; 167 return root; 168 } 169 170 171 // 返回指定节点的后继(后继的定义见算法导论) 172 Node *TreeSuccessor(Node *root) 173 { 174 if (root->right != NULL) 175 return TreeMinimum(root->right); 176 Node* tempParent = root->parent; 177 while (tempParent != NULL&&tempParent->left != root) 178 { 179 root = tempParent; 180 tempParent = tempParent->parent; 181 } 182 return tempParent; 183 } 184 185 // 为一颗红黑树节点设置颜色值; 186 187 void SetNodeColor(Node * root) 188 { 189 if (root != NIL) 190 { 191 cout << root->key << "颜色" << endl; 192 cin >> root->color; 193 SetNodeColor(root->left); 194 SetNodeColor(root->right); 195 } 196 } 197 198 // 按照中序访问建立红黑树但不涉及节点的颜色 199 void CreateRBTreeByArray(Node *root, int a[]) 200 { 201 //输入root的key 202 root->key = a[visited]; 203 visited++; 204 if (a[visited] == -1) 205 { 206 root->left = NIL; 207 visited++; 208 } 209 else 210 { 211 root->left = new Node(); 212 root->left->parent = root; 213 CreateRBTreeByArray(root->left, a); 214 } 215 if (a[visited] == -1) 216 { 217 root->right = NIL; 218 visited++; 219 } 220 else 221 { 222 root->right = new Node(); 223 root->right->parent = root; 224 CreateRBTreeByArray(root->right, a); 225 } 226 } 227 // 遍历一颗红黑树 228 void TraverseRBTree(Node *root) 229 { 230 if (root != NIL) 231 { 232 TraverseRBTree(root->left); 233 cout << root->key << "颜色:"; 234 if (root->color == 1) 235 cout << "Red" << endl; 236 else 237 cout << "Black" << endl; 238 TraverseRBTree(root->right); 239 } 240 } 241 242 void SetRBTreeColorByArray(Node *root, int a[]) 243 { 244 if (root != NIL) 245 { 246 SetRBTreeColorByArray(root->left, a); 247 root->color = a[colorFlag]; 248 colorFlag++; 249 SetRBTreeColorByArray(root->right, a); 250 } 251 } 252 253 // 作为普通二叉树的插入操作,但仍需要进一步调整 254 void RBInsert(Node *root, Node *z) 255 { 256 Node* x = root; 257 Node* y = x->parent; 258 while (x != NIL) 259 { 260 y = x; 261 if (z->key < x->key) 262 { 263 x = x->left; 264 } 265 else 266 { 267 x = x->right; 268 } 269 } 270 z->parent = y; 271 if (z->key < y->key) 272 y->left = z; 273 else 274 y->right = z; 275 z->left = NIL; 276 z->right = NIL; 277 z->color = Red; 278 } 279 280 void LeftRotate(Node* root, Node *x) 281 { 282 Node *y = x->right; 283 x->right = y->left; 284 if (y->left != NIL) 285 y->left->parent = x; 286 y->parent = x->parent; 287 if (x->parent == NIL) 288 Root = y; 289 if (x == x->parent->left) 290 x->parent->left = y; 291 else 292 x->parent->right = y; 293 y->left = x; 294 x->parent = y; 295 } 296 297 void RightRotate(Node *root, Node *y) 298 { 299 Node *x = y->left; 300 y->left = x->right; 301 if (x->right!=NIL) 302 y->left->parent = x; 303 x->parent = y->parent; 304 if (x->parent == NIL) 305 Root = x; 306 if (y == y->parent->left) 307 y->parent->left = x; 308 else 309 y->parent->right = x; 310 x->right = y; 311 y->parent = x; 312 } 313 314 void RBFixup(Node *root, Node *z) 315 { 316 while (z->parent->color == Red) 317 { 318 if (z->parent == z->parent->parent->left) 319 { 320 Node *y = z->parent->parent->right; 321 if (y->color == Red) 322 { 323 y->color = Black; 324 z->parent->color = Black; 325 y->parent->color = Red; 326 z = y->parent; 327 } 328 else if (z == z->parent->right) 329 { 330 z = z->parent; 331 LeftRotate(Root, z); 332 333 z->parent->color = Black; 334 z->parent->parent->color = Red; 335 RightRotate(Root, z->parent->parent); 336 } 337 else 338 { 339 z->parent->color = Black; 340 z->parent->color = Red; 341 RightRotate(root, z->parent->parent); 342 } 343 } 344 else 345 { 346 347 } 348 } 349 Root->color = Black; 350 } 351 352 int main() 353 { 354 // 建立NIL 355 NIL = new Node(); 356 NIL->key = -1; // 规定NIL的key等于-1; 357 358 int a[] = {11, 2, 1, -1, -1, 7, 5, -1, -1, 8, -1, -1, 14, -1, 15, -1, -1 }; 359 int color[] = { Black, Red, Red, Black, Red, Black, Black, Red}; 360 Node *treeroot = new Node(); 361 treeroot->key = 15; 362 treeroot->parent = NIL; 363 Root = treeroot; 364 visited = 0; 365 colorFlag = 0; 366 CreateRBTreeByArray(treeroot, a); 367 /*SetNodeColor(treeroot);*/ 368 SetRBTreeColorByArray(treeroot, color); 369 TraverseRBTree(treeroot); 370 Node* Insert = new Node(); 371 Insert->key = 6; 372 RBInsert(treeroot, Insert); 373 cout << TreeSearch(Root, 11)->color << endl; 374 RBFixup(treeroot, Insert); 375 cout << TreeSearch(Root, 11)->color << endl; 376 TraverseRBTree(Root); 377 cout << TreeSearch(Root, 11)->color << endl; 378 return 0; 379 }