AVL树(自平衡二叉查找树)

了解AVL树之前要先了解二叉查找树(BST),BST查找元素的时间复杂度平均是O(logN),最坏的情况是O(N),所有的元素都接在左子树(或者右子树)就相当于一串链表了。而AVL树会对子树过高的情况进行优化,这里有个平衡因子的概念,当前节点的平衡因子=左子树高度-右子树高度,AVL树的每一个节点的平衡因子的绝对值都是 < 2 的。

当一个新节点插入AVL树 ( 根节点为tree ) 的时候会有四种情况:

假设距离新节点最近的失衡节点为 t ( 的平衡因子的绝对值达到了2,且距离新节点最近)

1、LL型:新节点在 t1 的左孩子的左子树上,需要对 t 进行一次右旋操作;

AVL树(自平衡二叉查找树)

2、RR型:新节点在 t 的右孩子的右子树上,需要对 t 进行一次左旋操作;

AVL树(自平衡二叉查找树)

3、LR型:新节点在 t 的左孩子的右子树上,需要先对 t 的左孩子进行一次RR(左旋)操作,然后对 t 进行一次LL(右旋)操作;

AVL树(自平衡二叉查找树)

4、RL型:新节点在 t 的右孩子的左子树上,需要先对 t 的右孩子进行一次LL(右旋)操作,然后对 t 进行一次RR(左旋)操作;

AVL树(自平衡二叉查找树)

AVL树的实现代码如下:

  1 #include "pch.h"
  2 #include <iostream>
  3 #include <queue>
  4 #define ElementType int//自定义元素类型
  5 using namespace std;
  6 typedef struct node *AVLTree;
  7 struct node {
  8     ElementType key;
  9     int Height = 0;
 10     AVLTree left = NULL, right = NULL;
 11 };
 12 int Height(AVLTree tree);//求树的高度
 13 ElementType Max(ElementType a, ElementType b);
 14 AVLTree insert(AVLTree tree, ElementType &key);//在AVLTree中插入节点
 15 AVLTree LL_Rotation(AVLTree tree);//LL旋转
 16 AVLTree RR_Rotation(AVLTree tree);//RR旋转
 17 AVLTree LR_Rotation(AVLTree tree);//LR旋转
 18 AVLTree RL_Rotation(AVLTree tree);//RL旋转
 19 
 20 void levelTraversal(AVLTree tree);//层序遍历,用于测试
 21 
 22 /*用main函数来测试,给N个不同的数据,插入AVL树中,然后层序输出*/
 23 int main()
 24 {
 25     int N;
 26     ElementType key;
 27     AVLTree tree = NULL;
 28     scanf("%d", &N);
 29     for (int i = 0; i < N; i++) {
 30         cin >> key;
 31         tree = insert(tree, key);
 32     }
 33     levelTraversal(tree);
 34 }
 35 
 36 AVLTree insert(AVLTree tree, ElementType &key) {
 37     if (tree == NULL) {
 38         tree = new node();
 39         tree->key = key;
 40     }
 41     else if (key < tree->key) {
 42         tree->left = insert(tree->left, key);//key小于当前节点的值时继续往其左子树递归地插入
 43         if (Height(tree->left) - Height(tree->right) >= 2) {//左子树与右子树的高度差达到2的时候就要对当前节点进行旋转,这里由于是递归地执行,保证了平衡因子达到2的节点是最接近插入点的
 44             if (key < tree->left->key)
 45                 tree = LL_Rotation(tree);
 46             else
 47                 tree = LR_Rotation(tree);
 48         }
 49     }
 50     else {
 51         tree->right = insert(tree->right, key);
 52         if (Height(tree->right) - Height(tree->left) >= 2) {
 53             if (key > tree->right->key)
 54                 tree = RR_Rotation(tree);
 55             else
 56                 tree = RL_Rotation(tree);
 57         }
 58     }
 59     tree->Height = Max(Height(tree->left), Height(tree->right)) + 1;//当前节点的高度为其最大子树的高度+1
 60     return tree;
 61 }
 62 
 63 AVLTree LR_Rotation(AVLTree tree) {
 64     tree->left = RR_Rotation(tree->left);
 65     return LL_Rotation(tree);
 66 }
 67 
 68 AVLTree RL_Rotation(AVLTree tree) {
 69     tree->right = LL_Rotation(tree->right);
 70     return RR_Rotation(tree);
 71 }
 72 
 73 AVLTree RR_Rotation(AVLTree tree) {
 74     AVLTree tree2 = tree->right;
 75     tree->right = tree2->left;
 76     tree2->left = tree;
 77     tree->Height = Max(Height(tree->left), Height(tree->right)) + 1;
 78     tree2->Height = Max(Height(tree2->right), tree->Height) + 1;
 79     return tree2;
 80 }
 81 
 82 AVLTree LL_Rotation(AVLTree tree) {
 83     AVLTree tree2 = tree->left;
 84     tree->left = tree2->right;
 85     tree2->right = tree;
 86     tree->Height = Max(Height(tree->left), Height(tree->right)) + 1;
 87     tree2->Height = Max(Height(tree->left), tree->Height) + 1;
 88     return tree2;
 89 }
 90 
 91 int Height(AVLTree tree) {
 92     if (tree == NULL)
 93         return 0;
 94     return tree->Height;
 95 }
 96 
 97 ElementType Max(ElementType a, ElementType b) {
 98     return a > b ? a : b;
 99 }
100 
101 void levelTraversal(AVLTree tree)
102 {
103     queue <AVLTree> Q;
104     Q.push(tree);
105     while (!Q.empty()) {
106         AVLTree t = Q.front();
107         Q.pop();
108         cout << t->key << " ";
109         if (t->left != NULL)
110             Q.push(t->left);
111         if (t->right != NULL) 
112             Q.push(t->right);
113     }
114 }

 

上一篇:二叉查找树,平衡二叉树


下一篇:详解平衡二叉树(AVL)