Avl树
一 Avl树的性质
Avl树是带有平衡条件的二叉查找树,即Avl树中的每个节点的左子树和右子树的高度最多差1,为此,我们需要在Avl的节点域中记录height信息,此时Avl树节点的域有data、left、right、parent、height等5种信息。
计算当前节点的height时,只需计算左子节点与右子节点的高度较高者,并在此基础上加1即可。若节点不存在,则将高度定义为-1,由此可知叶子节点的高度为0。
1 int height(BinaryTreeNode *n) 2 { 3 return n ? n->height : -1; 4 } 5 6 int maxHeight(BinaryTreeNode *n) 7 { 8 int lh = height(n->left); 9 int rh = height(n->right); 10 return lh > rh ? lh+1 : rh+1; 11 }
一棵Avl树的高度最多为1.44log(N+2)-1.328。
容易看出,插入或删除节点操作后,将有4种情况使Avl树失衡,假设失衡的节点为n,则有:
① n的左子树比右子树的高度高2,且n的左子节点的左子树高度大于右子树
② n的左子树比右子树的高度高2,且n的左子节点的右子树高度大于左子树
③ n的右子树比左子树的高度高2,且n的右子节点的左子树高度大于右子树
④ n的右子树比左子树的高度高2,且n的右子节点的右子树高度大于左子树
二 Avl树的再平衡操作
对于以上四种情况,都可以采用左旋、右旋、左右双旋、右左双旋的操作使树再平衡。下面,我们来详细分析这四种情况:
1 n的左子树比右子树的高度高2,且n的左子节点的左子树高度大于右子树
此时,对于k2需要采用右旋操作,具体步骤如下
① 若k1的右子节点y存在,则使y的parent指向k2,k2的left指向y;若y不存在,k2的left为NULL。
② 将k1的parent指向k2的parent;若k2的parent为NULL(即k2为root),那么设root=k1,否则,设置k2->parent的left/right为k1。
③ 将k2的parent指向k1,将k1->right指向k2。
④ 重新计算k1、k2的高度
1 void rotateWithLeftChild(BinaryTreeNode *k2) 2 { 3 BinaryTreeNode *k1 = k2->left; 4 if (k1->right) 5 k1->right->parent = k2; 6 k2->left = k1->right; 7 k1->parent = k2->parent; 8 if (!k2->parent) 9 root = k1; 10 else if (k2 == k2->parent->left) 11 k2->parent->left = k1; 12 else if (k2 == k2->parent->right) 13 k2->parent->right = k1; 14 else 15 ; 16 k2->parent = k1; 17 k1->right = k2; 18 k1->height = maxHeight(k1); 19 k2->height = maxHeight(k2); 20 }
2 n的右子树比左子树的高度高2,且n的右子节点的右子树高度大于左子树
此时,对于k1需要采用右旋操作,具体步骤如下
① 若k2的左子节点y存在,则使y的parent指向k1,k1的right指向y;若y不存在,k1的right为NULL。
② 将k2的parent指向k1的parent;若k1的parent为NULL(即k1为root),那么设root=k2,否则,设置k1->parent的left/right为k2。
③ 将k1的parent指向k2,将k2->left指向k1。
④ 重新计算k1、k2的高度
1 void rotateWithRightChild(BinaryTreeNode *k1) 2 { 3 BinaryTreeNode *k2 = k1->right; 4 if (k2->left) 5 k2->left->parent = k1; 6 k1->right = k2->left; 7 k2->parent = k1->parent; 8 if (!k1->parent) 9 root = k2; 10 else if (k1 == k1->parent->left) 11 k1->parent->left = k2; 12 else if (k2 == k2->parent->right) 13 k1->parent->right = k2; 14 else 15 ; 16 k1->parent = k2; 17 k2->left = k1; 18 k1->height = maxHeight(k1); 19 k2->height = maxHeight(k2); 20 }
3 n的左子树比右子树的高度高2,且n的左子节点的右子树高度大于左子树
此时需要对k3采用左右双旋操作,具体步骤如下
① 对k1采用左旋操作
② 对k3采用右旋操作
1 void doubleRotateWithLeftChild(BinaryTreeNode *k3) 2 { 3 rotateWithRightChild(k3->left); 4 rotateWithLeftChild(k3); 5 }
4 n的右子树比左子树的高度高2,且n的右子节点的左子树高度大于右子树
此时需要对k1采用右左双旋操作,具体步骤如下
① 对k3采用右旋操作
② 对k1采用左旋操作
1 void doubleRotateWithRightChild(BinaryTreeNode *k1) 2 { 3 rotateWithLeftChild(k1->right); 4 rotateWithRightChild(k1); 5 }
三 Avl树的插入、删除操作
1 insert插入操作
在Avl树中插入节点时,除了进行二叉查找树的插入操作外,插入操作结束后需要:
①重新计算高度
②并根据高度差决定是否需要再平衡操作(若插入的是根节点,则不需要②③)
③如果需要再平衡,那么需要采用哪种旋转操作。
由于采用递归的实现方式,对失衡的节点进行再平衡操作后,还需向上搜索失衡节点直到根节点,从而保证了Avl树的性质。
1 void insert(Comparable d) 2 { 3 if (root) 4 insertNode(d, root); 5 else 6 root = new BinaryTreeNode(d); 7 8 root->height = maxHeight(root); 9 } 10 11 void insertNode(Comparable d, BinaryTreeNode *n) 12 { 13 if (d < n->data) 14 { 15 if (n->left) 16 insertNode(d, n->left); 17 else 18 { 19 n->left = new BinaryTreeNode(d); 20 n->left->parent = n; 21 } 22 n->left->height = maxHeight(n->left); 23 if (height(n->left) - height(n->right) == 2) 24 { 25 if (d < n->left->data) 26 rotateWithLeftChild(n); 27 else 28 doubleRotateWithLeftChild(n); 29 } 30 } 31 else if (d > n->data) 32 { 33 if (n->right) 34 insertNode(d, n->right); 35 else 36 { 37 n->right = new BinaryTreeNode(d); 38 n->right->parent = n; 39 } 40 n->right->height = maxHeight(n->right); 41 if (height(n->right) - height(n->left) == 2) 42 { 43 if (d > n->right->data) 44 rotateWithRightChild(n); 45 else 46 doubleRotateWithRightChild(n); 47 } 48 } 49 else 50 ; 51 }
2 remove移除操作
在Avl树中移除节点时,除了进行二叉树的移除操作外,移除操作后还需要:
① 向上遍历重新计算父节点的高度直到根节点。
② 并根据高度差决定是否需要再平衡操作
③ 如果需要再平衡,那么需要采用哪种旋转操作。
由于移除节点时不是逐层向下递归,所以再平衡操作需要重新编写向上逐层搜索的递归函数。
1 void remove(Comparable d) 2 { 3 BinaryTreeNode *n = searchNode(d); 4 5 if (n != NULL) 6 { 7 removeNode(n); 8 } 9 } 10 11 void removeNode(BinaryTreeNode *n) 12 { 13 if (!n) 14 return; 15 if (n->left && n->right) 16 { 17 //n->data = findPredeNode(n)->data; 18 //removeNode(findPredeNode(n)); 19 n->data = findSucNode(n)->data; 20 removeNode(findSucNode(n)); 21 } 22 else 23 { 24 BinaryTreeNode *x = (n->left) ? n->left : n->right; 25 if (n == root) 26 root = x; 27 else 28 { 29 BinaryTreeNode *p = n->parent; 30 31 if (n == p->left) 32 p->left = x; 33 else 34 p->right = x; 35 36 delete n; 37 n = NULL; 38 if (x) 39 x->parent = p; 40 decreaseHeight(p); 41 } 42 } 43 } 44 45 void decreaseHeight(BinaryTreeNode *n) 46 { 47 if (n) 48 { 49 n->height = maxHeight(n); 50 51 if ((height(n->left) - height(n->right)) == 2 ) 52 { 53 if (height(n->left->right) > height(n->left->left)) 54 doubleRotateWithLeftChild(n); 55 else 56 rotateWithLeftChild(n); 57 } 58 else if ((height(n->right) - height(n->left)) == 2) 59 { 60 if (height(n->right->left) > height(n->right->right)) 61 doubleRotateWithRightChild(n); 62 else 63 rotateWithRightChild(n); 64 } 65 else 66 ; 67 68 decreaseHeight(n->parent); 69 } 70 }
四 完整代码
4.1 AvlTree.hpp
1 #include <iostream> 2 3 using namespace std; 4 5 //Comparable必须重载 ① '>' ② '<' ③ '==' ④ '<<' 6 template <typename Comparable> 7 class AvlTree 8 { 9 public: 10 AvlTree() { root = NULL; } 11 AvlTree(const AvlTree *bst) { root = deepClone(bst->root); } 12 ~AvlTree() { makeEmpty(); } 13 14 AvlTree* operator=(const AvlTree *bst) 15 { 16 this->root = deepClone(bst->root); 17 return this; 18 } 19 20 Comparable findMin() 21 { 22 // 方法一 23 BinaryTreeNode *r = root; 24 BinaryTreeNode *p = NULL; 25 while (r) 26 { 27 p = r; 28 r = r->left; 29 } 30 if (p) 31 return p->data; 32 else 33 return -1; 34 // 方法二 35 //return findMinNode(root)->data; 36 } 37 38 Comparable findMax() 39 { 40 // 方法一 41 BinaryTreeNode *r = root; 42 BinaryTreeNode *p = NULL; 43 while (r) 44 { 45 p = r; 46 r = r->right; 47 } 48 if (p) 49 return p->data; 50 else 51 return -1; 52 // 方法二 53 //return findMaxNode(root)->data; 54 } 55 56 bool contains(Comparable d) 57 { 58 // 方法一 59 BinaryTreeNode *r = root; 60 while (r) 61 { 62 if (d < r->data) 63 r = r->left; 64 else if (d > r->data) 65 r = r->right; 66 else 67 return true; 68 } 69 return false; 70 // 方法二 71 //return searchNode(d) ? true : false; 72 } 73 74 Comparable findPredecessor(Comparable d) 75 { 76 BinaryTreeNode *n = searchNode(d); 77 if (n) 78 { 79 BinaryTreeNode *pre = findPredeNode(n); 80 81 if (pre) 82 return pre->data; 83 else 84 return n->data; 85 } 86 else 87 return d; 88 } 89 90 Comparable findSuccessor(Comparable d) 91 { 92 BinaryTreeNode *n = searchNode(d); 93 if (n) 94 { 95 BinaryTreeNode *suc = findSucNode(n); 96 97 if (suc) 98 return suc->data; 99 else 100 return n->data; 101 } 102 else 103 return d; 104 } 105 106 bool isEmpty() 107 { 108 return root ? false : true; 109 } 110 111 void makeEmpty() 112 { 113 makeEmpty(root); 114 } 115 116 void insert(Comparable d) 117 { 118 if (root) 119 insertNode(d, root); 120 else 121 root = new BinaryTreeNode(d); 122 123 root->height = maxHeight(root); 124 } 125 126 void remove(Comparable d) 127 { 128 BinaryTreeNode *n = searchNode(d); 129 130 if (n != NULL) 131 { 132 removeNode(n); 133 } 134 } 135 136 void printTree() 137 { 138 if (root) 139 { 140 printTree(root); 141 cout << endl; 142 } 143 else 144 cout << "树中没有数据" << endl; 145 } 146 147 private: 148 struct BinaryTreeNode 149 { 150 Comparable data; 151 BinaryTreeNode *left; 152 BinaryTreeNode *right; 153 BinaryTreeNode *parent; 154 int height; 155 156 BinaryTreeNode(Comparable d, BinaryTreeNode *l=NULL, BinaryTreeNode *r=NULL, BinaryTreeNode *p=NULL, int h=0): data(d), left(l), right(r), parent(p), height(h) { } 157 }; 158 159 BinaryTreeNode *root; 160 161 BinaryTreeNode* deepClone(BinaryTreeNode *n) 162 { 163 if (n) 164 { 165 BinaryTreeNode *p = new BinaryTreeNode(n->data, deepClone(n->left), deepClone(n->right), NULL, n->height); 166 if (p->left) 167 p->left->parent = p; 168 if (p->right) 169 p->right->parent = p; 170 return p; 171 } 172 return NULL; 173 } 174 175 BinaryTreeNode* findMinNode(BinaryTreeNode *n) 176 { 177 if (n->left) 178 return findMinNode(n->left); 179 return n; 180 } 181 182 BinaryTreeNode* findMaxNode(BinaryTreeNode *n) 183 { 184 if (n->right) 185 return findMaxNode(n->right); 186 return n; 187 } 188 189 BinaryTreeNode* searchNode(Comparable d) 190 { 191 BinaryTreeNode *r = root; 192 while (r) 193 { 194 if (d < r->data) 195 r = r->left; 196 else if (d > r->data) 197 r = r->right; 198 else 199 return r; 200 } 201 return NULL; 202 } 203 204 BinaryTreeNode* findPredeNode(BinaryTreeNode *n) 205 { 206 BinaryTreeNode *p = NULL; 207 if (n->left) 208 return findMaxNode(n->left); 209 p = n->parent; 210 while (p && n == p->left) 211 { 212 n = p; 213 p = p->parent; 214 } 215 return p; 216 } 217 218 BinaryTreeNode* findSucNode(BinaryTreeNode *n) 219 { 220 BinaryTreeNode *p = NULL; 221 if (n->right) 222 return findMinNode(n->right); 223 p = n->parent; 224 while (p && n == p->right) 225 { 226 n = p; 227 p = p->parent; 228 } 229 return p; 230 } 231 232 void makeEmpty(BinaryTreeNode *&n) // 需要改变指针参数 233 { 234 if (n) 235 { 236 makeEmpty(n->left); 237 makeEmpty(n->right); 238 delete n; 239 n = NULL; 240 } 241 return; 242 } 243 244 void insertNode(Comparable d, BinaryTreeNode *n) 245 { 246 if (d < n->data) 247 { 248 if (n->left) 249 insertNode(d, n->left); 250 else 251 { 252 n->left = new BinaryTreeNode(d); 253 n->left->parent = n; 254 } 255 n->left->height = maxHeight(n->left); 256 if (height(n->left) - height(n->right) == 2) 257 { 258 if (d < n->left->data) 259 rotateWithLeftChild(n); 260 else 261 doubleRotateWithLeftChild(n); 262 } 263 } 264 else if (d > n->data) 265 { 266 if (n->right) 267 insertNode(d, n->right); 268 else 269 { 270 n->right = new BinaryTreeNode(d); 271 n->right->parent = n; 272 } 273 n->right->height = maxHeight(n->right); 274 if (height(n->right) - height(n->left) == 2) 275 { 276 if (d > n->right->data) 277 rotateWithRightChild(n); 278 else 279 doubleRotateWithRightChild(n); 280 } 281 } 282 else 283 ; 284 } 285 286 void removeNode(BinaryTreeNode *n) 287 { 288 if (!n) 289 return; 290 if (n->left && n->right) 291 { 292 //n->data = findPredeNode(n)->data; 293 //removeNode(findPredeNode(n)); 294 n->data = findSucNode(n)->data; 295 removeNode(findSucNode(n)); 296 } 297 else 298 { 299 BinaryTreeNode *x = (n->left) ? n->left : n->right; 300 if (n == root) 301 root = x; 302 else 303 { 304 BinaryTreeNode *p = n->parent; 305 306 if (n == p->left) 307 p->left = x; 308 else 309 p->right = x; 310 311 delete n; 312 n = NULL; 313 if (x) 314 x->parent = p; 315 decreaseHeight(p); 316 } 317 } 318 } 319 320 void printTree(BinaryTreeNode *r) 321 { 322 if (!r) 323 return; 324 printTree(r->left); 325 cout << r->data << "(" << r->height << ")" << " "; 326 printTree(r->right); 327 } 328 329 int height(BinaryTreeNode *n) 330 { 331 return n ? n->height : -1; 332 } 333 334 int maxHeight(BinaryTreeNode *n) 335 { 336 int lh = height(n->left); 337 int rh = height(n->right); 338 return lh > rh ? lh+1 : rh+1; 339 } 340 341 void decreaseHeight(BinaryTreeNode *n) 342 { 343 if (n) 344 { 345 n->height = maxHeight(n); 346 347 if ((height(n->left) - height(n->right)) == 2 ) 348 { 349 if (height(n->left->right) > height(n->left->left)) 350 doubleRotateWithLeftChild(n); 351 else 352 rotateWithLeftChild(n); 353 } 354 else if ((height(n->right) - height(n->left)) == 2) 355 { 356 if (height(n->right->left) > height(n->right->right)) 357 doubleRotateWithRightChild(n); 358 else 359 rotateWithRightChild(n); 360 } 361 else 362 ; 363 364 decreaseHeight(n->parent); 365 } 366 } 367 368 void rotateWithLeftChild(BinaryTreeNode *k2) 369 { 370 BinaryTreeNode *k1 = k2->left; 371 if (k1->right) 372 k1->right->parent = k2; 373 k2->left = k1->right; 374 k1->parent = k2->parent; 375 if (!k2->parent) 376 root = k1; 377 else if (k2 == k2->parent->left) 378 k2->parent->left = k1; 379 else if (k2 == k2->parent->right) 380 k2->parent->right = k1; 381 else 382 ; 383 k2->parent = k1; 384 k1->right = k2; 385 k1->height = maxHeight(k1); 386 k2->height = maxHeight(k2); 387 } 388 389 void rotateWithRightChild(BinaryTreeNode *k1) 390 { 391 BinaryTreeNode *k2 = k1->right; 392 if (k2->left) 393 k2->left->parent = k1; 394 k1->right = k2->left; 395 k2->parent = k1->parent; 396 if (!k1->parent) 397 root = k2; 398 else if (k1 == k1->parent->left) 399 k1->parent->left = k2; 400 else if (k2 == k2->parent->right) 401 k1->parent->right = k2; 402 else 403 ; 404 k1->parent = k2; 405 k2->left = k1; 406 k1->height = maxHeight(k1); 407 k2->height = maxHeight(k2); 408 } 409 410 void doubleRotateWithLeftChild(BinaryTreeNode *k3) 411 { 412 rotateWithRightChild(k3->left); 413 rotateWithLeftChild(k3); 414 } 415 416 void doubleRotateWithRightChild(BinaryTreeNode *k1) 417 { 418 rotateWithLeftChild(k1->right); 419 rotateWithRightChild(k1); 420 } 421 };
4.2 main.cpp
1 #include <ctime> 2 #include <iostream> 3 #include <cstdlib> 4 5 #include "AvlTree.hpp" 6 7 using namespace std; 8 9 const int LENGTH = 9; 10 11 void generateTree(AvlTree<int> *tree) 12 { 13 srand((unsigned int)time(NULL)); 14 int i = LENGTH; 15 while(i--) 16 { 17 tree->insert(rand() % 100); 18 tree->printTree(); 19 } 20 } 21 22 void checkDeepClone(AvlTree<int> *tree) 23 { 24 AvlTree<int> *newTree = tree; 25 //AvlTree<int> *newTree = new AvlTree<int>(tree); 26 cout << "数据拷贝完成" << endl; 27 newTree->printTree(); 28 } 29 30 void checkMinMax(AvlTree<int> *tree) 31 { 32 cout << "Min: " << tree->findMin() << endl; 33 cout << "Max: " << tree->findMax() << endl; 34 } 35 36 void checkContains(AvlTree<int> *tree) 37 { 38 int elem; 39 cout << "请输入用来测试是否包含的数据: "; 40 cin >> elem; 41 if (tree->contains(elem)) 42 cout << "存在" << endl; 43 else 44 cout << "不存在" << endl; 45 } 46 47 void checkPreSuc(AvlTree<int> *tree) 48 { 49 int elem; 50 cout << "请输入用来测试前趋后继的数据: "; 51 cin >> elem; 52 cout << elem << "的前趋为" << tree->findPredecessor(elem) << endl; 53 cout << elem << "的后继为" << tree->findSuccessor(elem) << endl; 54 } 55 56 void checkEmpty(AvlTree<int> *tree) 57 { 58 if (tree->isEmpty()) 59 cout << "树为空" << endl; 60 else 61 cout << "树不为空" << endl; 62 63 tree->makeEmpty(); 64 tree->printTree(); 65 66 if (tree->isEmpty()) 67 cout << "树为空" << endl; 68 else 69 cout << "树不为空" << endl; 70 } 71 72 void checkRemove(AvlTree<int> *tree) 73 { 74 if (tree->isEmpty()) 75 { 76 generateTree(tree); 77 tree->printTree(); 78 } 79 while (!tree->isEmpty()) 80 { 81 int elem; 82 cout << "请输入要移除的数据: "; 83 cin >> elem; 84 tree->remove(elem); 85 tree->printTree(); 86 87 } 88 } 89 90 int main() 91 { 92 AvlTree<int> *tree = new AvlTree<int>(); 93 generateTree(tree); 94 tree->printTree(); 95 96 //checkDeepClone(tree); 97 98 checkMinMax(tree); 99 100 //checkContains(tree); 101 //checkContains(tree); 102 103 //checkPreSuc(tree); 104 //checkPreSuc(tree); 105 //checkPreSuc(tree); 106 //checkPreSuc(tree); 107 108 //checkEmpty(tree); 109 110 checkRemove(tree); 111 112 system("pause"); 113 }
4.3 运行结果截图