BST, AVL Tree 和 Splay Tree 的实现
一、定义。
1.1 BST
二叉搜索树,也称有序二叉树,排序二叉树,是指一棵空树或者具有下列性质的二叉树:
① 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
② 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
③ 任意节点的左、右子树也分别为二叉查找树。
④ 没有键值相等的节点。
1.2 AVL Tree
平衡二叉树定义(AVL):它或者是一颗空树,或者具有以下性质的二叉树:它的左子树和右子树的深度之差(平衡因子)的绝对值不超过1,且它的左子树和右子树都是一颗平衡二叉树。
平衡因子(bf):结点的左子树的深度减去右子树的深度。
保持平衡是依赖于旋转操作,分为LL, RR, LR, RL四种情况。
LL单旋即右旋。
1.3 Splay Tree
伸展树的出发点是这样的:考虑到局部性原理(刚被访问的内容下次可能仍会被访问,查找次数多的内容可能下一次会被访问),为了使整个查找时间更小,被查频率高的那些节点应当经常处于靠近树根的位置。这样,很容易得想到以下这个方案:每次查找节点之后对树进行重构,把被查找的节点搬移到树根,这种自调整形式的二叉查找树就是伸展树。每次对伸展树进行操作后,它均会通过旋转的方法把被访问节点旋转到树根的位置。
为了将当前被访问节点旋转到树根,我们通常将节点自底向上旋转,直至该节点成为树根为止。“旋转”的巧妙之处就是在不打乱数列中数据大小关系(指中序遍历结果是全序的)情况下,所有基本操作的平摊复杂度仍为O(log n)。
伸展树主要有三种旋转操作,分别为单旋转,一字形旋转和之字形旋转。为了便于解释,我们假设当前被访问节点为X,X的父亲节点为Y(如果X的父亲节点存在),X的祖父节点为Z(如果X的祖父节点存在)。这里的单旋与之字形旋转与AVL树是一致的,因此这里只列出Zig-Zig。
Splay操作可以自底向上也可以自顶向下,我只实现了自底向上的算法,自顶向下以后有机会再补充,因为每次操作都需要把操作的结点翻转到根,所以用Zig-Zig代替单旋,每次上升两层,如果根节点恰好是父节点,则此时只需要一次单旋。
二、复杂度分析。
AVL无论是在顺序逆序或者随机插入删除的情况下效果都不错,而Splay在按照顺序或者逆序的情况下效果比较好,因为预测准确,而随机则无法预测,所做的Splay操作都是多余的,所以比较慢,AVL 和 Splay 哪个更合适需要具体情况具体分析。
2.1 BST
Algorithm | Average | Worst case | |
---|---|---|---|
Space | O(n) | O(n) | |
Search | O(log n) | O(n) | |
Insert | O(log n) | O(n) | |
Delete | O(log n) | O(n) |
2.2 AVL Tree
Algorithm | Average | Worst case | |
---|---|---|---|
Space | O(n) | O(n) | |
Search | O(log n) |
O(log n) |
|
Insert | O(log n) |
O(log n) |
|
Delete | O(log n) |
O(log n) |
2.3 Splay Tree
Algorithm | Average | Worst case | |
---|---|---|---|
Space | O(n) | O(n) | |
Search | O(log n) | amortized O(log n) | |
Insert | O(log n) | amortized O(log n) | |
Delete | O(log n) | amortized O(log n) |
三、实现。
水平有限,写的比较啰嗦,见谅。
1 #include <iostream> 2 using namespace std; 3 // Binery Search Tree Node 4 class BSTreeNode { 5 public: 6 int data; 7 BSTreeNode* leftChild; 8 BSTreeNode* rightChild; 9 BSTreeNode(int value): data(value), leftChild(NULL), rightChild(NULL){} 10 }; 11 // AVL Tree Node 12 class AVLTreeNode { 13 public: 14 int data; 15 // The height of node 16 int height; 17 AVLTreeNode* leftChild; 18 AVLTreeNode* rightChild; 19 AVLTreeNode(int value): data(value), height(0), leftChild(NULL), rightChild(NULL){} 20 }; 21 // Splay Tree Node 22 class SplayTreeNode { 23 public: 24 int data; 25 // The pointer to parent 26 SplayTreeNode* parent; 27 SplayTreeNode* leftChild; 28 SplayTreeNode* rightChild; 29 SplayTreeNode(int value): data(value), parent(NULL), leftChild(NULL), rightChild(NULL){} 30 }; 31 // Preorder traversal 32 void previsit(SplayTreeNode* T){ 33 if(T){ 34 cout<<T->data<<' '; 35 previsit(T->leftChild); 36 previsit(T->rightChild); 37 } 38 39 } 40 // Preorder traversal 41 void previsit(BSTreeNode* T){ 42 if(T!=NULL){ 43 cout<<T->data<<' '; 44 previsit(T->leftChild); 45 previsit(T->rightChild); 46 } 47 } 48 // Preorder traversal 49 void previsit(AVLTreeNode* T){ 50 if(T){ 51 cout<<T->data<<' '; 52 previsit(T->leftChild); 53 previsit(T->rightChild); 54 } 55 56 } 57 // Find the minimun element 58 BSTreeNode* BSTreeFindMin(BSTreeNode* T) { 59 if (T == NULL) { 60 return NULL; 61 } else if (T->leftChild == NULL) { 62 return T; 63 } else { 64 return BSTreeFindMin(T->leftChild); 65 } 66 } 67 // Insert operation of Binery Search Tree 68 BSTreeNode* BSTreeInsert(int value, BSTreeNode* T) { 69 if (T == NULL) { 70 T = new BSTreeNode(value); 71 } else { 72 // If value is smaller than element 73 if (value < T->data) { 74 T->leftChild = BSTreeInsert(value, T->leftChild); 75 } 76 // If value is larger than element 77 else if (value > T->data) { 78 T->rightChild = BSTreeInsert(value, T->rightChild); 79 } 80 } 81 return T; 82 } 83 // Delete operation of Binery Search Tree 84 BSTreeNode* BSTreeDelete(int value, BSTreeNode* T) { 85 if (T == NULL) { 86 return NULL; 87 } 88 // If value is smaller than element 89 else if (value < T->data) { 90 T->leftChild = BSTreeDelete(value, T->leftChild); 91 } 92 // If value is larger than element 93 else if (value > T->data) { 94 T->rightChild = BSTreeDelete(value, T->rightChild); 95 } 96 // If value is equal to element 97 else { 98 if (T->leftChild && T->rightChild) { 99 // Two children 100 BSTreeNode* tmp = BSTreeFindMin(T->rightChild); 101 T->data = tmp->data; 102 //delete tmp; 103 T->rightChild = BSTreeDelete(T->data, T->rightChild); 104 } else { 105 // One or no child 106 if (T->leftChild) { 107 T = T->leftChild; 108 } else if (T->rightChild) { 109 T = T->rightChild; 110 } else { 111 T = NULL; 112 } 113 } 114 } 115 return T; 116 } 117 // Get the height of AVL Tree 118 int getHeight(AVLTreeNode* T) { 119 if (T == NULL) { 120 return -1; 121 } else { 122 return T->height; 123 } 124 } 125 // Get the larger one element 126 int Max(int x, int y) { 127 return (x > y) ? x : y; 128 } 129 // LL Rotation 130 AVLTreeNode* SingleRotateWithLeft(AVLTreeNode* K2) { 131 AVLTreeNode* K1; 132 133 K1 = K2->leftChild; 134 K2->leftChild = K1->rightChild; 135 K1->rightChild = K2; 136 137 // Update the height of node 138 K2->height = Max(getHeight(K2->leftChild), getHeight(K2->rightChild)) + 1; 139 K1->height = Max(getHeight(K1->leftChild), getHeight(K1->rightChild)) + 1; 140 return K1; 141 } 142 // RR Rotation 143 AVLTreeNode* SingleRotateWithRight(AVLTreeNode* K2) { 144 AVLTreeNode* K1; 145 146 K1 = K2->rightChild; 147 K2->rightChild = K1->leftChild; 148 K1->leftChild = K2; 149 150 // Update the height of node 151 K2->height = Max(getHeight(K2->leftChild), getHeight(K2->rightChild)) + 1; 152 K1->height = Max(getHeight(K1->leftChild), getHeight(K1->rightChild)) + 1; 153 return K1; 154 } 155 // LR Rotation 156 AVLTreeNode* DoubleRotateWithLeft(AVLTreeNode* K3) { 157 K3->leftChild = SingleRotateWithRight(K3->leftChild); 158 return SingleRotateWithLeft(K3); 159 } 160 // RL Rotation 161 AVLTreeNode* DoubleRotateWithRight(AVLTreeNode* K3) { 162 K3->rightChild = SingleRotateWithLeft(K3->rightChild); 163 return SingleRotateWithRight(K3); 164 } 165 // Find the minimum element 166 AVLTreeNode* AVLTreeFindMin(AVLTreeNode* T) { 167 if (T == NULL) { 168 return NULL; 169 } else if (T->leftChild == NULL) { 170 return T; 171 } else { 172 return AVLTreeFindMin(T->leftChild); 173 } 174 } 175 // Insert operation of AVL Tree 176 AVLTreeNode* AVLTreeInsert(int value, AVLTreeNode* T) { 177 if (T == NULL) { 178 T = new AVLTreeNode(value); 179 return T; 180 } else { 181 // If value is smaller than element 182 if (value < T->data) { 183 T->leftChild = AVLTreeInsert(value, T->leftChild); 184 // If the balance is broken 185 if (getHeight(T->leftChild) - getHeight(T->rightChild) == 2) { 186 if (value < T->leftChild->data) { 187 // LL Rotation 188 T = SingleRotateWithLeft(T); 189 } else { 190 // LR Rotation 191 T = DoubleRotateWithLeft(T); 192 } 193 } 194 } 195 // If value is larger than element 196 else if (value > T->data) { 197 T->rightChild = AVLTreeInsert(value, T->rightChild); 198 // If the balance is broken 199 if (getHeight(T->rightChild) - getHeight(T->leftChild) == 2) { 200 if (value > T->rightChild->data) { 201 // RR Rotation 202 T = SingleRotateWithRight(T); 203 } else { 204 // RL Rotation 205 T = DoubleRotateWithRight(T); 206 } 207 } 208 } 209 210 // Update the height of node 211 if (T) { 212 T->height = Max(getHeight(T->leftChild), getHeight(T->rightChild)) + 1; 213 } 214 return T; 215 } 216 } 217 // Delete operation of AVL Tree 218 AVLTreeNode* AVLTreeDelete(int value, AVLTreeNode* T) { 219 if (T == NULL) { 220 return NULL; 221 } else { 222 // If value is smaller than element 223 if (value < T->data) { 224 T->leftChild = AVLTreeDelete(value, T->leftChild); 225 // If the balance is broken 226 if (getHeight(T->rightChild) - getHeight(T->leftChild) == 2) { 227 // Delete is similar to insert 228 // We can assume the unbalance is caused by insert an element 229 if (getHeight(T->rightChild->rightChild) >= getHeight(T->rightChild->leftChild)) { 230 // RR Rotation 231 T = SingleRotateWithRight(T); 232 } else { 233 // RL Rotation 234 T = DoubleRotateWithRight(T); 235 } 236 } 237 } 238 // If value is larger than element 239 else if (value > T->data) { 240 T->rightChild = AVLTreeDelete(value, T->rightChild); 241 // If the balance is broken 242 if (getHeight(T->leftChild) - getHeight(T->rightChild) == 2) { 243 // Delete is similar to insert 244 // We can assume the unbalance is caused by insert an element 245 if (getHeight(T->leftChild->leftChild) >= getHeight(T->leftChild->rightChild)) { 246 // LL Rotation 247 T = SingleRotateWithLeft(T); 248 } else { 249 // LR Rotation 250 T = DoubleRotateWithLeft(T); 251 } 252 } 253 } 254 // If value is equal to element 255 else { 256 if (T->leftChild && T->rightChild) { 257 // Two children 258 AVLTreeNode* tmp = AVLTreeFindMin(T->rightChild); 259 T->data = tmp->data; 260 //delete tmp; 261 T->rightChild = AVLTreeDelete(T->data, T->rightChild); 262 } else { 263 // One or no child 264 if (T->leftChild) { 265 T = T->leftChild; 266 } else if (T->rightChild) { 267 T = T->rightChild; 268 } else { 269 T = NULL; 270 } 271 } 272 } 273 } 274 275 // Update the height of node 276 if (T) { 277 T->height = Max(getHeight(T->leftChild), getHeight(T->rightChild)) + 1; 278 } 279 return T; 280 } 281 // LL Rotation of Splay Tree 282 SplayTreeNode* SplaySingleRotateWithLeft(SplayTreeNode* K2) { 283 // It is similar to AVL Tree 284 // But we must update the parent of node 285 SplayTreeNode* K1 = K2->leftChild; 286 SplayTreeNode* P = K2->parent; 287 K2->leftChild = K1->rightChild; 288 if(K2->leftChild){ 289 K2->leftChild->parent = K2; 290 } 291 K1->rightChild = K2; 292 K1->rightChild->parent = K1; 293 K1->parent = P; 294 if (P != NULL) { 295 if (P->leftChild == K2) { 296 P->leftChild = K1; 297 } else { 298 P->rightChild = K1; 299 } 300 } 301 return K1; 302 } 303 // RR Rotation of Splay Tree 304 SplayTreeNode* SplaySingleRotateWithRight(SplayTreeNode* K2) { 305 // It is similar to AVL Tree 306 // But we must update the parent of node 307 SplayTreeNode* K1 = K2->rightChild; 308 SplayTreeNode* P = K2->parent; 309 K2->rightChild = K1->leftChild; 310 if(K2->rightChild){ 311 K2->rightChild->parent = K2; 312 } 313 K1->leftChild = K2; 314 if(K1->leftChild){ 315 K1->leftChild->parent = K1; 316 } 317 318 K1->parent = P; 319 if (P != NULL) { 320 if (P->leftChild == K2) { 321 P->leftChild = K1; 322 } else { 323 P->rightChild = K1; 324 } 325 } 326 return K1; 327 } 328 // LR Rotation 329 SplayTreeNode* SplayDoubleRotateWithLeft(SplayTreeNode* K3) { 330 K3->leftChild = SplaySingleRotateWithRight(K3->leftChild); 331 return SplaySingleRotateWithLeft(K3); 332 } 333 // RL Rotation 334 SplayTreeNode* SplayDoubleRotateWithRight(SplayTreeNode* K3) { 335 K3->rightChild = SplaySingleRotateWithLeft(K3->rightChild); 336 return SplaySingleRotateWithRight(K3); 337 } 338 // L-Zig-Zig 339 SplayTreeNode* ZigZigWithLeft(SplayTreeNode* K3) { 340 SplayTreeNode* parent = K3->parent; 341 SplayTreeNode* K2 = K3->leftChild; 342 SplayTreeNode* K1 = K2->leftChild; 343 344 K3->leftChild = K2->rightChild; 345 if (K2->rightChild != NULL) { 346 K3->leftChild->parent = K3; 347 } 348 K2->rightChild = K3; 349 K2->rightChild->parent = K2; 350 K2->leftChild = K1->rightChild; 351 if (K1->rightChild != NULL) { 352 K2->leftChild->parent = K2; 353 } 354 K1->rightChild = K2; 355 K1->rightChild->parent = K1; 356 K1->parent = parent; 357 if (parent != NULL) { 358 if (parent->leftChild == K3) { 359 parent->leftChild = K1; 360 } else { 361 parent->rightChild = K1; 362 } 363 } 364 return K1; 365 } 366 // R-Zig-Zig 367 SplayTreeNode* ZigZigWithRight(SplayTreeNode* K3) { 368 SplayTreeNode* parent = K3->parent; 369 SplayTreeNode* K2 = K3->leftChild; 370 SplayTreeNode* K1 = K2->leftChild; 371 372 K3->rightChild = K2->leftChild; 373 if (K2->leftChild != NULL) { 374 K3->rightChild->parent = K3; 375 } 376 K2->leftChild = K3; 377 K2->leftChild->parent = K2; 378 K2->rightChild = K1->leftChild; 379 if (K1->leftChild != NULL) { 380 K2->rightChild->parent = K2; 381 } 382 K1->leftChild = K2; 383 K1->leftChild->parent = K1; 384 K1->parent = parent; 385 if (parent != NULL) { 386 if (parent->leftChild == K3) { 387 parent->leftChild = K1; 388 } else { 389 parent->rightChild = K1; 390 } 391 } 392 return K1; 393 } 394 // Insert operation of Splay Tree without Splay 395 // It is similar to insert operation of Binery Search Tree 396 SplayTreeNode* PreInsert(int value, SplayTreeNode* T) { 397 if (T == NULL) { 398 T = new SplayTreeNode(value); 399 } else { 400 if (value < T->data) { 401 T->leftChild = PreInsert(value, T->leftChild); 402 // Update the parent of node 403 T->leftChild->parent = T; 404 } else if (value > T->data) { 405 T->rightChild = PreInsert(value, T->rightChild); 406 // Update the parent of node 407 T->rightChild->parent = T; 408 } 409 } 410 return T; 411 } 412 // Find the maximum element 413 SplayTreeNode* SplayTreeFindMax(SplayTreeNode* T) { 414 if (T == NULL) { 415 return NULL; 416 } else if (T->rightChild == NULL) { 417 return T; 418 } else { 419 return SplayTreeFindMax(T->rightChild); 420 } 421 } 422 // Find the minimum element 423 SplayTreeNode* SplayTreeFindMin(SplayTreeNode* T) { 424 if (T == NULL) { 425 return NULL; 426 } else if (T->leftChild == NULL) { 427 return T; 428 } else { 429 return SplayTreeFindMin(T->leftChild); 430 } 431 } 432 // Find the element and return the node 433 SplayTreeNode* Find(int value, SplayTreeNode* T) { 434 if (T == NULL) { 435 return NULL; 436 } else if (T->data == value) { 437 return T; 438 } else if (T->data > value) { 439 return Find(value, T->leftChild); 440 } else { 441 return Find(value, T->rightChild); 442 } 443 } 444 // Splay operation of Splay Tree 445 SplayTreeNode* Splay(int value, SplayTreeNode* T) { 446 SplayTreeNode* K = Find(value, T); 447 // Parent node 448 SplayTreeNode* P = NULL; 449 // Grandparent node 450 SplayTreeNode* GP = NULL; 451 // If node doesn't exist 452 if (K == NULL) { 453 return T; 454 } 455 // Do rotation until K arrives at root or is the child of root 456 while (T->leftChild != K && T->rightChild != K) { 457 P = K->parent; 458 // Break the loop if just need single rotation 459 if(P==NULL||P->parent==NULL){ 460 break; 461 } 462 GP = P->parent; 463 if (GP->leftChild == P && P->leftChild == K) { 464 // L-Zig-Zig 465 ZigZigWithLeft(GP); 466 } else if (GP->leftChild == P && P->rightChild == K) { 467 // LR Rotation 468 SplayDoubleRotateWithLeft(GP); 469 } else if (GP->rightChild == P && P->leftChild == K) { 470 // RL Rotation 471 SplayDoubleRotateWithRight(GP); 472 } else if (GP->rightChild == P && P->rightChild == K) { 473 // R-Zig-Zig 474 ZigZigWithRight(GP); 475 } 476 // Return the new root if GP == T 477 if(GP == T){ 478 return K; 479 } 480 } 481 if (T->leftChild == K) { 482 // LL Rotation 483 T = SplaySingleRotateWithLeft(T); 484 } else if (T->rightChild == K) { 485 // RR Rotation 486 T = SplaySingleRotateWithRight(T); 487 } 488 return T; 489 } 490 // Insert operation of Splay Tree 491 SplayTreeNode* SplayTreeInsert(int value, SplayTreeNode* T) { 492 // First insert the element just like Binery Search Tree 493 T = PreInsert(value, T); 494 // Then do the Splay 495 T = Splay(value, T); 496 } 497 // Splay operation of Splay Tree 498 SplayTreeNode* Splay(SplayTreeNode* node, SplayTreeNode* T) { 499 SplayTreeNode* K = node; 500 // Parent node 501 SplayTreeNode* P = NULL; 502 // Grandparent node 503 SplayTreeNode* GP = NULL; 504 // If node doesn't exist 505 if(K == NULL){ 506 return T; 507 } 508 // Do rotation until K arrives at root or is the child of root 509 while (T->leftChild != K && T->rightChild != K) { 510 P = K->parent; 511 // Break the loop if just need single rotation 512 if(P==NULL||P->parent==NULL){ 513 break; 514 } 515 GP = P->parent; 516 if (GP->leftChild == P && P->leftChild == K) { 517 // L-Zig-Zig 518 ZigZigWithLeft(GP); 519 } else if (GP->leftChild == P && P->rightChild == K) { 520 // LR Rotation 521 SplayDoubleRotateWithLeft(GP); 522 } else if (GP->rightChild == P && P->leftChild == K) { 523 // RL Rotation 524 SplayDoubleRotateWithRight(GP); 525 } else if (GP->rightChild == P && P->rightChild == K) { 526 // R-Zig-Zig 527 ZigZigWithRight(GP); 528 } 529 // Return the new root if GP == T 530 if(GP == T){ 531 return K; 532 } 533 } 534 if (T->leftChild == K) { 535 // LL Rotation 536 T = SplaySingleRotateWithLeft(T); 537 } else if (T->rightChild == K) { 538 // RR Rotation 539 T = SplaySingleRotateWithRight(T); 540 } 541 return T; 542 } 543 // Delete operation of Splay Tree 544 SplayTreeNode* SplayTreeDelete(int value, SplayTreeNode* T) { 545 // If T is NULL 546 if (!T) { 547 return NULL; 548 } 549 // First do the Splay operation 550 T = Splay(value, T); 551 // Leftchild of root 552 SplayTreeNode* L = T->leftChild; 553 // Rightchild of root 554 SplayTreeNode* R = T->rightChild; 555 // If the tree doesn't have rightchild 556 if(R==NULL){ 557 R = L; 558 if (L) { 559 R->parent = NULL; 560 } 561 } 562 else{ 563 R->parent = NULL; 564 // Find the minimum element of R 565 R = Splay(SplayTreeFindMin(R), R); 566 R-> leftChild = L; 567 if(L){ 568 L->parent = R; 569 } 570 } 571 // Delete the element 572 delete T; 573 return R; 574 }