目录
二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查
找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii
和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。
1、空树也是一颗AVL树
2、它的左右子树都是AVL树
3、左右子树高度差(平衡因子)的绝对值不超过1
4、如果一颗二叉搜索树是高度平衡的,它就是AVL树。如果它由N个节点,其高度可保持在O(log2N),搜索时间复杂度为O(log2N)。

- template<class K, class V>
- struct AVLTreeNode
- {
- AVLTreeNode(const pair
& kv) - :_kv(kv)
- ,_parent(nullptr)
- ,_left(nullptr)
- ,_right(nullptr)
- ,_bf(0)//平衡因子初始为0
- {}
-
- pair
_kv; - AVLTreeNode* _parent;
- AVLTreeNode* _left;
- AVLTreeNode* _right;
- int _bf;//平衡因子 —— balance factor
- };
AVL树的插入分为两大步:
1、新建节点,插入到正确的位置(使之符合二叉搜索树的性质)
如果插入到右边,则平衡因子加1,如果插入到左边,平衡因子减1;
2、判断平衡因子是否合法,不合法则调整节点(旋转)
插入完成后平衡因子有以下几种情况:
如果此时parent的平衡因子为0,那么之前的平衡因子是1或-1,这棵树的高度不会变,不用向上更新,插入完成。
如果此时parent的平衡因子为1或-1,那么之前的平衡因子为0,高度改变了,需要向上更新。
如果此时parent的平衡因子为2或-2,那么需要通过旋转调平衡。

- void RotateL(Node* parent)
- {
- Node* cur = parent->_right;
- Node* curleft = cur->_left;
-
- parent->_right = curleft;
- cur->_left = parent;
- if (curleft)
- curleft->_parent = parent;
-
- Node* ppnode = parent->_parent;
- parent->_parent = cur;
-
- if (parent == _root)
- {
- cur->_parent = nullptr;
- _root = cur;
- }
- else
- {
- if (ppnode->_left == parent)
- {
- ppnode->_left = cur;
- }
- else
- {
- ppnode->_right = cur;
- }
- cur->_parent = ppnode;
- }
- parent->_bf = cur->_bf = 0;//更新平衡因子
- }

- void RotateR(Node* parent)
- {
- Node* cur = parent->_left;
- Node* curright = cur->_right;
-
- parent->_left = curright;
- cur->_right = parent;
-
- if (curright)
- curright->_parent = parent;
-
- Node* ppnode = parent->_parent;
- parent->_parent = cur;
-
- if (parent == _root)
- {
- cur->_parent = nullptr;
- _root = cur;
- }
- else
- {
- if (ppnode->_left == parent)
- {
- ppnode->_left = cur;
- }
- else
- {
- ppnode->_right = cur;
- }
- cur->_parent = ppnode;
- }
- parent->_bf = cur->_bf = 0;
- }

- void RotateLR(Node* parent)
- {
- Node* cur = parent->_left;
- Node* curright = cur->_right;
- int bf = curright->_bf;
-
- RotateL(parent->_left);
- RotateR(parent);
-
- //更新平衡因子
- if (bf == 0)
- {
- parent->_bf = curright->_bf = cur->_bf = 0;
- }
- else if (bf == 1)
- {
- parent->_bf = 0;
- cur->_bf = -1;
- curright = 0;
- }
- else if (bf == -1)
- {
- parent->_bf = 1;
- cur->_bf = 0;
- curright = 0;
- }
- else
- {
- assert(false);
- }
- }

- void RotateRL(Node* parent)
- {
- Node* cur = parent->_right;
- Node* curleft = cur->_left;
- int bf = curleft->_bf;
-
- RotateR(parent->_right);
- RotateL(parent);
-
- //更新平衡因子
- if (bf == 0)
- {
- parent->_bf = curleft->_bf = cur->_bf = 0;
- }
- else if (bf == 1)
- {
- parent->_bf = -1;
- cur->_bf = 0;
- curleft = 0;
- }
- else if (bf == -1)
- {
- parent->_bf = 0;
- cur->_bf = 1;
- curleft = 0;
- }
- else
- {
- assert(false);
- }
- }
- bool insert(const pair
& kv) - {
- //如果root为空
- if (_root == nullptr)
- {
- _root = new Node(kv);
- return true;
- }
- //插入
- Node* cur = _root;
- Node* parent = cur;
-
- while (cur)
- {
- if (cur->_kv.first < kv.first)
- {
- parent = cur;
- cur = cur->_right;
- }
- else if (cur->_kv.first > kv.first)
- {
- parent = cur;
- cur = cur->_left;
- }
- else
- {
- return false;
- }
- }
- cur = new Node(kv);
- if (parent->_kv.first < kv.first)
- {
- parent->_right = cur;
- }
- else
- {
- parent->_left = cur;
- }
- cur->_parent = parent;//刚开始忘记写了
-
- //插入完成,开始判断是否平衡
- //最坏走到根就不再判断了,根的parent为空
- while (parent)
- {
- //更新平衡因子
- if (parent->_left == cur)
- {
- parent->_bf--;
- }
- else
- {
- parent->_bf++;
- }
- //如果此时parent的平衡因子为0,那么之前的平衡因子是1或-1,这棵树的高度不会变,不用向上更新
- if (parent->_bf == 0)
- {
- break;
- }
- //如果此时parent的平衡因子为1或-1,那么之前的平衡因子为0,高度改变了,需要向上更新
- else if (parent->_bf == 1 || parent->_bf == -1)
- {
- //向上更新
- cur = parent;
- parent = parent->_parent;
- }
- //如果此时parent的平衡因子为2或-2,那么需要通过旋转调平衡
- else if (parent->_bf == 2 || parent->_bf == -2)
- {
- //左单旋
- if (parent->_bf == 2 && cur->_bf == 1)
- {
- RotateL(parent);
- }
- //右单旋
- if(parent->_bf == -2 && cur->_bf == -1)
- {
- RotateR(parent);
- }
- //先右单旋,再左单旋
- if (parent->_bf == 2 && cur->_bf == -1)
- {
- RotateRL(parent);
- }
- //先左单旋,再右单旋
- if (parent->_bf == -2 && cur->_bf == 1)
- {
- RotateLR(parent);
- }
-
- break;//忘记写了
- }
- else
- {
- assert(false);
- }
- }
- return true;
- }
- bool isBalance()
- {
- return _isBalance(_root);
- }
-
- int Height(Node* root)
- {
- if (root == nullptr)
- return 0;
- int lh = Height(root->_left);
- int rh = Height(root->_right);
-
- return lh > rh ? lh + 1 : rh + 1;
- }
-
- bool _isBalance(Node* root)
- {
- if (root == nullptr)
- return true;
- int leftHeight = Height(root->_left);
- int rightHeight = Height(root->_right);
- int diff = abs(rightHeight - leftHeight);
- return diff <= 1 && _isBalance(root->_left) && _isBalance(root->_right);
- }
- int main()
- {
- //常规场景
- AVLTree<int, int>* root1 = new AVLTree<int, int>();
- int a1[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
- for (auto e : a1)
- {
- root1->insert(make_pair(e, e));
- }
- root1->InOrder();
- cout << "isBalance: " << root1->isBalance() << endl;
-
- //特殊场景
- AVLTree<int, int>* root2 = new AVLTree<int, int>();
- int a2[] = { 4,2,6,1,3,5,15,7,16,14 };
- for (auto e : a2)
- {
- root2->insert(make_pair(e, e));
- }
- root2->InOrder();
- cout << "isBalance: " << root2->isBalance() << endl;
-
- //随机数
- const int N = 100000;
- vector<int> v;
- v.reserve(N);
- srand(time(0));
- for (int i = 0; i < N; i++)
- {
- int n = rand();
- v.push_back(n);
- }
- AVLTree<int, int>* root3 = new AVLTree<int, int>();
- for (auto e : v)
- {
- root3->insert(make_pair(e, e));
- }
- //root->InOrder();
- cout << "isBalance: " << root3->isBalance() << endl;
- return 0;
- }
运行结果:
