一、AVL树的介绍
AVL树是高度平衡的而二叉树。
它的特点是:AVL树中任何节点的两个子树的高度最大差别为1。
二、AVL树的C++实现
1. 节点
1.1 AVL树节点
1 template <class T> 2 class AVLTreeNode{ 3 public: 4 T key; // 关键字(键值) 5 int height; // 高度 6 AVLTreeNode *left; // 左孩子 7 AVLTreeNode *right; // 右孩子 8 9 AVLTreeNode(T value, AVLTreeNode *l, AVLTreeNode *r): 10 key(value), height(0),left(l),right(r) {} 11 };
AVLTreeNode是AVL树的节点类,它包括的几个组成对象:
(1) key -- 是关键字,是用来对AVL树的节点进行排序的。
(2) left -- 是左孩子。
(3) right -- 是右孩子。
(4) height -- 是高度。
1.2 AVL树
1 template <class T> 2 class AVLTree { 3 private: 4 AVLTreeNode<T> *mRoot; // 根结点 5 6 public: 7 AVLTree(); 8 ~AVLTree(); 9 10 // 获取树的高度 11 int height(); 12 // 获取树的高度 13 int max(int a, int b); 14 15 // 前序遍历"AVL树" 16 void preOrder(); 17 // 中序遍历"AVL树" 18 void inOrder(); 19 // 后序遍历"AVL树" 20 void postOrder(); 21 22 // (递归实现)查找"AVL树"中键值为key的节点 23 AVLTreeNode<T>* search(T key); 24 // (非递归实现)查找"AVL树"中键值为key的节点 25 AVLTreeNode<T>* iterativeSearch(T key); 26 27 // 查找最小结点:返回最小结点的键值。 28 T minimum(); 29 // 查找最大结点:返回最大结点的键值。 30 T maximum(); 31 32 // 将结点(key为节点键值)插入到AVL树中 33 void insert(T key); 34 35 // 删除结点(key为节点键值) 36 void remove(T key); 37 38 // 销毁AVL树 39 void destroy(); 40 41 // 打印AVL树 42 void print(); 43 private: 44 // 获取树的高度 45 int height(AVLTreeNode<T>* tree) ; 46 47 // 前序遍历"AVL树" 48 void preOrder(AVLTreeNode<T>* tree) const; 49 // 中序遍历"AVL树" 50 void inOrder(AVLTreeNode<T>* tree) const; 51 // 后序遍历"AVL树" 52 void postOrder(AVLTreeNode<T>* tree) const; 53 54 // (递归实现)查找"AVL树x"中键值为key的节点 55 AVLTreeNode<T>* search(AVLTreeNode<T>* x, T key) const; 56 // (非递归实现)查找"AVL树x"中键值为key的节点 57 AVLTreeNode<T>* iterativeSearch(AVLTreeNode<T>* x, T key) const; 58 59 // 查找最小结点:返回tree为根结点的AVL树的最小结点。 60 AVLTreeNode<T>* minimum(AVLTreeNode<T>* tree); 61 // 查找最大结点:返回tree为根结点的AVL树的最大结点。 62 AVLTreeNode<T>* maximum(AVLTreeNode<T>* tree); 63 64 // LL:左左对应的情况(左单旋转)。 65 AVLTreeNode<T>* leftLeftRotation(AVLTreeNode<T>* k2); 66 67 // RR:右右对应的情况(右单旋转)。 68 AVLTreeNode<T>* rightRightRotation(AVLTreeNode<T>* k1); 69 70 // LR:左右对应的情况(左双旋转)。 71 AVLTreeNode<T>* leftRightRotation(AVLTreeNode<T>* k3); 72 73 // RL:右左对应的情况(右双旋转)。 74 AVLTreeNode<T>* rightLeftRotation(AVLTreeNode<T>* k1); 75 76 // 将结点(z)插入到AVL树(tree)中 77 AVLTreeNode<T>* insert(AVLTreeNode<T>* &tree, T key); 78 79 // 删除AVL树(tree)中的结点(z),并返回被删除的结点 80 AVLTreeNode<T>* remove(AVLTreeNode<T>* &tree, AVLTreeNode<T>* z); 81 82 // 销毁AVL树 83 void destroy(AVLTreeNode<T>* &tree); 84 85 // 打印AVL树 86 void print(AVLTreeNode<T>* tree, T key, int direction); 87 };
AVLTree是AVL树对应的类。它包含AVL树的根节点mRoot和AVL树的基本操作接口。需要说明的是:AVLTree中重载了许多函数。重载的目的是区分内部接口和外部接口,例如insert()函数而言,insert(tree, key)是内部接口,而insert(key)是外部接口。
1.2 树的高度
1 /* 2 * 获取树的高度 3 */ 4 template <class T> 5 int AVLTree<T>::height(AVLTreeNode<T>* tree) 6 { 7 if (tree != NULL) 8 return tree->height; 9 10 return 0; 11 } 12 13 template <class T> 14 int AVLTree<T>::height() 15 { 16 return height(mRoot); 17 }
1.3 比较大小
/* * 比较两个值的大小 */ template <class T> int AVLTree<T>::max(int a, int b) { return a>b ? a : b; }
如果在AVL树中进行插入或删除节点后,可能导致AVL树失去平衡。AVL失去平衡之后,可以通过旋转使其恢复平衡。具体的旋转原理和实现参见:http://www.cnblogs.com/skywang12345/p/3577360.html
注意:关于AVL树的"前序遍历"、"中序遍历"、"后序遍历"、"最大值"、"最小值"、"查找"、"打印"、"销毁"等接口与"二叉查找树"基本一样,
【完整示例】
AVLTree.h
1 #ifndef _AVL_TREE_HPP_ 2 #define _AVL_TREE_HPP_ 3 4 #include <iomanip> 5 #include <iostream> 6 using namespace std; 7 8 template <class T> 9 class AVLTreeNode{ 10 public: 11 T key; // 关键字(键值) 12 int height; // 高度 13 AVLTreeNode *left; // 左孩子 14 AVLTreeNode *right; // 右孩子 15 16 AVLTreeNode(T value, AVLTreeNode *l, AVLTreeNode *r): 17 key(value), height(0),left(l),right(r) {} 18 }; 19 20 template <class T> 21 class AVLTree { 22 private: 23 AVLTreeNode<T> *mRoot; // 根结点 24 25 public: 26 AVLTree(); 27 ~AVLTree(); 28 29 // 获取树的高度 30 int height(); 31 // 获取树的高度 32 int max(int a, int b); 33 34 // 前序遍历"AVL树" 35 void preOrder(); 36 // 中序遍历"AVL树" 37 void inOrder(); 38 // 后序遍历"AVL树" 39 void postOrder(); 40 41 // (递归实现)查找"AVL树"中键值为key的节点 42 AVLTreeNode<T>* search(T key); 43 // (非递归实现)查找"AVL树"中键值为key的节点 44 AVLTreeNode<T>* iterativeSearch(T key); 45 46 // 查找最小结点:返回最小结点的键值。 47 T minimum(); 48 // 查找最大结点:返回最大结点的键值。 49 T maximum(); 50 51 // 将结点(key为节点键值)插入到AVL树中 52 void insert(T key); 53 54 // 删除结点(key为节点键值) 55 void remove(T key); 56 57 // 销毁AVL树 58 void destroy(); 59 60 // 打印AVL树 61 void print(); 62 private: 63 // 获取树的高度 64 int height(AVLTreeNode<T>* tree) ; 65 66 // 前序遍历"AVL树" 67 void preOrder(AVLTreeNode<T>* tree) const; 68 // 中序遍历"AVL树" 69 void inOrder(AVLTreeNode<T>* tree) const; 70 // 后序遍历"AVL树" 71 void postOrder(AVLTreeNode<T>* tree) const; 72 73 // (递归实现)查找"AVL树x"中键值为key的节点 74 AVLTreeNode<T>* search(AVLTreeNode<T>* x, T key) const; 75 // (非递归实现)查找"AVL树x"中键值为key的节点 76 AVLTreeNode<T>* iterativeSearch(AVLTreeNode<T>* x, T key) const; 77 78 // 查找最小结点:返回tree为根结点的AVL树的最小结点。 79 AVLTreeNode<T>* minimum(AVLTreeNode<T>* tree); 80 // 查找最大结点:返回tree为根结点的AVL树的最大结点。 81 AVLTreeNode<T>* maximum(AVLTreeNode<T>* tree); 82 83 // LL:左左对应的情况(左单旋转)。 84 AVLTreeNode<T>* leftLeftRotation(AVLTreeNode<T>* k2); 85 86 // RR:右右对应的情况(右单旋转)。 87 AVLTreeNode<T>* rightRightRotation(AVLTreeNode<T>* k1); 88 89 // LR:左右对应的情况(左双旋转)。 90 AVLTreeNode<T>* leftRightRotation(AVLTreeNode<T>* k3); 91 92 // RL:右左对应的情况(右双旋转)。 93 AVLTreeNode<T>* rightLeftRotation(AVLTreeNode<T>* k1); 94 95 // 将结点(z)插入到AVL树(tree)中 96 AVLTreeNode<T>* insert(AVLTreeNode<T>* &tree, T key); 97 98 // 删除AVL树(tree)中的结点(z),并返回被删除的结点 99 AVLTreeNode<T>* remove(AVLTreeNode<T>* &tree, AVLTreeNode<T>* z); 100 101 // 销毁AVL树 102 void destroy(AVLTreeNode<T>* &tree); 103 104 // 打印AVL树 105 void print(AVLTreeNode<T>* tree, T key, int direction); 106 }; 107 108 /* 109 * 构造函数 110 */ 111 template <class T> 112 AVLTree<T>::AVLTree():mRoot(NULL) 113 { 114 } 115 116 /* 117 * 析构函数 118 */ 119 template <class T> 120 AVLTree<T>::~AVLTree() 121 { 122 destroy(mRoot); 123 } 124 125 /* 126 * 获取树的高度 127 */ 128 template <class T> 129 int AVLTree<T>::height(AVLTreeNode<T>* tree) 130 { 131 if (tree != NULL) 132 return tree->height; 133 134 return 0; 135 } 136 137 template <class T> 138 int AVLTree<T>::height() 139 { 140 return height(mRoot); 141 } 142 /* 143 * 比较两个值的大小 144 */ 145 template <class T> 146 int AVLTree<T>::max(int a, int b) 147 { 148 return a>b ? a : b; 149 } 150 151 /* 152 * 前序遍历"AVL树" 153 */ 154 template <class T> 155 void AVLTree<T>::preOrder(AVLTreeNode<T>* tree) const 156 { 157 if(tree != NULL) 158 { 159 cout<< tree->key << " " ; 160 preOrder(tree->left); 161 preOrder(tree->right); 162 } 163 } 164 165 template <class T> 166 void AVLTree<T>::preOrder() 167 { 168 preOrder(mRoot); 169 } 170 171 /* 172 * 中序遍历"AVL树" 173 */ 174 template <class T> 175 void AVLTree<T>::inOrder(AVLTreeNode<T>* tree) const 176 { 177 if(tree != NULL) 178 { 179 inOrder(tree->left); 180 cout<< tree->key << " " ; 181 inOrder(tree->right); 182 } 183 } 184 185 template <class T> 186 void AVLTree<T>::inOrder() 187 { 188 inOrder(mRoot); 189 } 190 191 /* 192 * 后序遍历"AVL树" 193 */ 194 template <class T> 195 void AVLTree<T>::postOrder(AVLTreeNode<T>* tree) const 196 { 197 if(tree != NULL) 198 { 199 postOrder(tree->left); 200 postOrder(tree->right); 201 cout<< tree->key << " " ; 202 } 203 } 204 205 template <class T> 206 void AVLTree<T>::postOrder() 207 { 208 postOrder(mRoot); 209 } 210 211 /* 212 * (递归实现)查找"AVL树x"中键值为key的节点 213 */ 214 template <class T> 215 AVLTreeNode<T>* AVLTree<T>::search(AVLTreeNode<T>* x, T key) const 216 { 217 if (x==NULL || x->key==key) 218 return x; 219 220 if (key < x->key) 221 return search(x->left, key); 222 else 223 return search(x->right, key); 224 } 225 226 template <class T> 227 AVLTreeNode<T>* AVLTree<T>::search(T key) 228 { 229 return search(mRoot, key); 230 } 231 232 /* 233 * (非递归实现)查找"AVL树x"中键值为key的节点 234 */ 235 template <class T> 236 AVLTreeNode<T>* AVLTree<T>::iterativeSearch(AVLTreeNode<T>* x, T key) const 237 { 238 while ((x!=NULL) && (x->key!=key)) 239 { 240 if (key < x->key) 241 x = x->left; 242 else 243 x = x->right; 244 } 245 246 return x; 247 } 248 249 template <class T> 250 AVLTreeNode<T>* AVLTree<T>::iterativeSearch(T key) 251 { 252 return iterativeSearch(mRoot, key); 253 } 254 255 /* 256 * 查找最小结点:返回tree为根结点的AVL树的最小结点。 257 */ 258 template <class T> 259 AVLTreeNode<T>* AVLTree<T>::minimum(AVLTreeNode<T>* tree) 260 { 261 if (tree == NULL) 262 return NULL; 263 264 while(tree->left != NULL) 265 tree = tree->left; 266 return tree; 267 } 268 269 template <class T> 270 T AVLTree<T>::minimum() 271 { 272 AVLTreeNode<T> *p = minimum(mRoot); 273 if (p != NULL) 274 return p->key; 275 276 return (T)NULL; 277 } 278 279 /* 280 * 查找最大结点:返回tree为根结点的AVL树的最大结点。 281 */ 282 template <class T> 283 AVLTreeNode<T>* AVLTree<T>::maximum(AVLTreeNode<T>* tree) 284 { 285 if (tree == NULL) 286 return NULL; 287 288 while(tree->right != NULL) 289 tree = tree->right; 290 return tree; 291 } 292 293 template <class T> 294 T AVLTree<T>::maximum() 295 { 296 AVLTreeNode<T> *p = maximum(mRoot); 297 if (p != NULL) 298 return p->key; 299 300 return (T)NULL; 301 } 302 303 /* 304 * LL:左左对应的情况(左单旋转)。 305 * 306 * 返回值:旋转后的根节点 307 */ 308 template <class T> 309 AVLTreeNode<T>* AVLTree<T>::leftLeftRotation(AVLTreeNode<T>* k2) 310 { 311 AVLTreeNode<T>* k1; 312 313 k1 = k2->left; 314 k2->left = k1->right; 315 k1->right = k2; 316 317 k2->height = max( height(k2->left), height(k2->right)) + 1; 318 k1->height = max( height(k1->left), k2->height) + 1; 319 320 return k1; 321 } 322 323 /* 324 * RR:右右对应的情况(右单旋转)。 325 * 326 * 返回值:旋转后的根节点 327 */ 328 template <class T> 329 AVLTreeNode<T>* AVLTree<T>::rightRightRotation(AVLTreeNode<T>* k1) 330 { 331 AVLTreeNode<T>* k2; 332 333 k2 = k1->right; 334 k1->right = k2->left; 335 k2->left = k1; 336 337 k1->height = max( height(k1->left), height(k1->right)) + 1; 338 k2->height = max( height(k2->right), k1->height) + 1; 339 340 return k2; 341 } 342 343 /* 344 * LR:左右对应的情况(左双旋转)。 345 * 346 * 返回值:旋转后的根节点 347 */ 348 template <class T> 349 AVLTreeNode<T>* AVLTree<T>::leftRightRotation(AVLTreeNode<T>* k3) 350 { 351 k3->left = rightRightRotation(k3->left); 352 353 return leftLeftRotation(k3); 354 } 355 356 /* 357 * RL:右左对应的情况(右双旋转)。 358 * 359 * 返回值:旋转后的根节点 360 */ 361 template <class T> 362 AVLTreeNode<T>* AVLTree<T>::rightLeftRotation(AVLTreeNode<T>* k1) 363 { 364 k1->right = leftLeftRotation(k1->right); 365 366 return rightRightRotation(k1); 367 } 368 369 /* 370 * 将结点插入到AVL树中,并返回根节点 371 * 372 * 参数说明: 373 * tree AVL树的根结点 374 * key 插入的结点的键值 375 * 返回值: 376 * 根节点 377 */ 378 template <class T> 379 AVLTreeNode<T>* AVLTree<T>::insert(AVLTreeNode<T>* &tree, T key) 380 { 381 if (tree == NULL) 382 { 383 // 新建节点 384 tree = new AVLTreeNode<T>(key, NULL, NULL); 385 if (tree==NULL) 386 { 387 cout << "ERROR: create avltree node failed!" << endl; 388 return NULL; 389 } 390 } 391 else if (key < tree->key) // 应该将key插入到"tree的左子树"的情况 392 { 393 tree->left = insert(tree->left, key); 394 // 插入节点后,若AVL树失去平衡,则进行相应的调节。 395 if (height(tree->left) - height(tree->right) == 2) 396 { 397 if (key < tree->left->key) 398 tree = leftLeftRotation(tree); 399 else 400 tree = leftRightRotation(tree); 401 } 402 } 403 else if (key > tree->key) // 应该将key插入到"tree的右子树"的情况 404 { 405 tree->right = insert(tree->right, key); 406 // 插入节点后,若AVL树失去平衡,则进行相应的调节。 407 if (height(tree->right) - height(tree->left) == 2) 408 { 409 if (key > tree->right->key) 410 tree = rightRightRotation(tree); 411 else 412 tree = rightLeftRotation(tree); 413 } 414 } 415 else //key == tree->key) 416 { 417 cout << "添加失败:不允许添加相同的节点!" << endl; 418 } 419 420 tree->height = max( height(tree->left), height(tree->right)) + 1; 421 422 return tree; 423 } 424 425 template <class T> 426 void AVLTree<T>::insert(T key) 427 { 428 insert(mRoot, key); 429 } 430 431 /* 432 * 删除结点(z),返回根节点 433 * 434 * 参数说明: 435 * tree AVL树的根结点 436 * z 待删除的结点 437 * 返回值: 438 * 根节点 439 */ 440 template <class T> 441 AVLTreeNode<T>* AVLTree<T>::remove(AVLTreeNode<T>* &tree, AVLTreeNode<T>* z) 442 { 443 // 根为空 或者 没有要删除的节点,直接返回NULL。 444 if (tree==NULL || z==NULL) 445 return NULL; 446 447 if (z->key < tree->key) // 待删除的节点在"tree的左子树"中 448 { 449 tree->left = remove(tree->left, z); 450 // 删除节点后,若AVL树失去平衡,则进行相应的调节。 451 if (height(tree->right) - height(tree->left) == 2) 452 { 453 AVLTreeNode<T> *r = tree->right; 454 if (height(r->left) > height(r->right)) 455 tree = rightLeftRotation(tree); 456 else 457 tree = rightRightRotation(tree); 458 } 459 } 460 else if (z->key > tree->key)// 待删除的节点在"tree的右子树"中 461 { 462 tree->right = remove(tree->right, z); 463 // 删除节点后,若AVL树失去平衡,则进行相应的调节。 464 if (height(tree->left) - height(tree->right) == 2) 465 { 466 AVLTreeNode<T> *l = tree->left; 467 if (height(l->right) > height(l->left)) 468 tree = leftRightRotation(tree); 469 else 470 tree = leftLeftRotation(tree); 471 } 472 } 473 else // tree是对应要删除的节点。 474 { 475 // tree的左右孩子都非空 476 if ((tree->left!=NULL) && (tree->right!=NULL)) 477 { 478 if (height(tree->left) > height(tree->right)) 479 { 480 // 如果tree的左子树比右子树高; 481 // 则(01)找出tree的左子树中的最大节点 482 // (02)将该最大节点的值赋值给tree。 483 // (03)删除该最大节点。 484 // 这类似于用"tree的左子树中最大节点"做"tree"的替身; 485 // 采用这种方式的好处是:删除"tree的左子树中最大节点"之后,AVL树仍然是平衡的。 486 AVLTreeNode<T>* max = maximum(tree->left); 487 tree->key = max->key; 488 tree->left = remove(tree->left, max); 489 } 490 else 491 { 492 // 如果tree的左子树不比右子树高(即它们相等,或右子树比左子树高1) 493 // 则(01)找出tree的右子树中的最小节点 494 // (02)将该最小节点的值赋值给tree。 495 // (03)删除该最小节点。 496 // 这类似于用"tree的右子树中最小节点"做"tree"的替身; 497 // 采用这种方式的好处是:删除"tree的右子树中最小节点"之后,AVL树仍然是平衡的。 498 AVLTreeNode<T>* min = maximum(tree->right); 499 tree->key = min->key; 500 tree->right = remove(tree->right, min); 501 } 502 } 503 else 504 { 505 AVLTreeNode<T>* tmp = tree; 506 tree = (tree->left!=NULL) ? tree->left : tree->right; 507 delete tmp; 508 } 509 } 510 511 return tree; 512 } 513 514 template <class T> 515 void AVLTree<T>::remove(T key) 516 { 517 AVLTreeNode<T>* z; 518 519 if ((z = search(mRoot, key)) != NULL) 520 mRoot = remove(mRoot, z); 521 } 522 523 /* 524 * 销毁AVL树 525 */ 526 template <class T> 527 void AVLTree<T>::destroy(AVLTreeNode<T>* &tree) 528 { 529 if (tree==NULL) 530 return ; 531 532 if (tree->left != NULL) 533 destroy(tree->left); 534 if (tree->right != NULL) 535 destroy(tree->right); 536 537 delete tree; 538 } 539 540 template <class T> 541 void AVLTree<T>::destroy() 542 { 543 destroy(mRoot); 544 } 545 546 /* 547 * 打印"二叉查找树" 548 * 549 * key -- 节点的键值 550 * direction -- 0,表示该节点是根节点; 551 * -1,表示该节点是它的父结点的左孩子; 552 * 1,表示该节点是它的父结点的右孩子。 553 */ 554 template <class T> 555 void AVLTree<T>::print(AVLTreeNode<T>* tree, T key, int direction) 556 { 557 if(tree != NULL) 558 { 559 if(direction==0) // tree是根节点 560 cout << setw(2) << tree->key << " is root" << endl; 561 else // tree是分支节点 562 cout << setw(2) << tree->key << " is " << setw(2) << key << "'s " << setw(12) << (direction==1?"right child" : "left child") << endl; 563 564 print(tree->left, tree->key, -1); 565 print(tree->right,tree->key, 1); 566 } 567 } 568 569 template <class T> 570 void AVLTree<T>::print() 571 { 572 if (mRoot != NULL) 573 print(mRoot, mRoot->key, 0); 574 } 575 #endif
main.cpp
1 #include <iostream> 2 #include "AVLTree.h" 3 using namespace std; 4 5 static int arr[]= {3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9}; 6 #define TBL_SIZE(a) ( (sizeof(a)) / (sizeof(a[0])) ) 7 8 int main() 9 { 10 int i,ilen; 11 AVLTree<int>* tree=new AVLTree<int>(); 12 13 cout << "== 依次添加: "; 14 ilen = TBL_SIZE(arr); 15 for(i=0; i<ilen; i++) 16 { 17 cout << arr[i] <<" "; 18 tree->insert(arr[i]); 19 } 20 21 cout << " == 前序遍历: "; 22 tree->preOrder(); 23 24 cout << " == 中序遍历: "; 25 tree->inOrder(); 26 27 cout << " == 后序遍历: "; 28 tree->postOrder(); 29 cout << endl; 30 31 cout << "== 高度: " << tree->height() << endl; 32 cout << "== 最小值: " << tree->minimum() << endl; 33 cout << "== 最大值: " << tree->maximum() << endl; 34 cout << "== 树的详细信息: " << endl; 35 tree->print(); 36 37 i = 8; 38 cout << " == 删除根节点: " << i; 39 tree->remove(i); 40 41 cout << " == 高度: " << tree->height() ; 42 cout << " == 中序遍历: " ; 43 tree->inOrder(); 44 cout << " == 树的详细信息: " << endl; 45 tree->print(); 46 47 // 销毁二叉树 48 tree->destroy(); 49 50 return 0; 51 }