AVL解决二叉搜索树退化成链表,保证左右子树高度不差过1,尽可能接近满二叉树
AVL树的性质:高度差(平衡因子)的绝对值不超过1(-1/0/1)
平衡因子:右子树高度-左子树高度
用平衡因子控制高度
AVL树节点
- class AVLTreeNode
- {
- pair
_kv; //key/value - AVLTreeNode
* _left; // 左 - AVLTreeNode
* _right;// 右 - AVLTreeNode
* _partent;// 父母 - int _bf;// 平衡因子
- AVLTreeNode(const pair
& kv) - :_kv(kv)
- ,_left(nullptr)
- ,_right(nullptr)
- ,_parent(nullptr)
- ,_bf(0)
- {}
- };
控制逻辑:增加一个新节点cur
parent的bf值-1,在右 ,parent的bf加1
如果parent_bf=0,则不再改变,否则继续向上调整,直到parent为0,或者为cur为根节点时。
如果parent的平衡因子为2或者-2,说明树不平衡,要进行旋转调整。
当左边高时(parent=2,cur=1)
柱子a,b,c表示高度为h的AVL树
- parent->right=cur->left
- cur->left=parent
对于左单旋的理解:1.根节点向左转,2.c树高度增加后a树高2,于是把c的父节点当成根节点使得c的高度方向-1,a的树的方向+1,刚好平衡
同时调整平衡因子数量和parent指针
左单旋
- void RotateL(Node* parent)
- {
- Node* cur = parent->_right; //确定cur
- Node* curleft = parent->_left;
- parent->_left = curleft;
- //当h不为0时
- if (curleft)
- {
- //调整parent指针
- curleft->_partent = parent;
- }
- cur->_left = parent;
- //调整新的根节点的parent指针
- Node* ppnode = parent->_parent;
- parent->_parent = cur;
- //根节点特殊情况
- if (parent == _root)
- {
- _root = cur;
- cur->_partent = nullptr;
- }
- else
- {
- // 确定parent是ppnode的左指针还是右指针
- if (ppnode->_left==parent)
- {
- ppnode->_left = cur;
- }
- else
- {
- ppnode_right = cur;
- }
- cur->_partent = ppnode;
- }
- parent->_bf = cur->_bf = 0;
- }
- void RotateR()
- {
- void RotateR(Node* parent)
- {
- Node* cur = parent->_left;
- Node* curright = cur->_right;
- parent->_left = curright;
- cur->_right = parent;
-
- Node* ppnode = parent->_parent;
- if (curright)
- {
- curright->_partent = parent;
- }
- parent->_parent = cur;
- if (ppnode == root)
- {
- _root = cur;
- cur->_partent = nullptr;
- }
- else
- {
- if (ppnode->_left == parent)
- {
- ppnode->_left = cur;
- }
- else(ppnode->_right == parent)
- {
- ppnode->_right = cur;
- }
- }
- cur->_bf = parent->_bf = 0;
-
- }
- }
双旋:我们发现左右双旋都是在都是a,c树高度发生变化,具体体现在cur和parent的平衡因子都是相差1,而如果在b树发生变化,无论是左边高还是右边高都会产生双旋问题。具体可以分为四种情况,现在以一种情况为例:
如下图是右边高的b树(现为60-b-c子树)发生改变。
从图上来讲是90进行右旋,把高的树的树移到外面,再30进行左旋,构建平衡。
对于父节点为60的树来说,左树成为30节点的右树,右树成为90节点的左树。
所以60的节点的双旋后30,60,90的_bf值不恒为0,30,90节点会受到60的影响。
当60->_bf=1, 30,60,90 =-1 ,0,0
60->_bf=-1, 30,60,90 = 1,0,0
当
左高右高的区别都是60做根节点,且_bf变化是一样的。
左高:先左旋后右旋,右高,先右旋后左旋。
插入代码和旋转代码
- bool Insert(const pair
& kv) - {
- if (_root == nullptr)
- {
- _root = new Node(kv);
- return true;
- }
- Node* parent = nullptr;
- Node* cur = _root;
- 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 if (parent->_kv.first > kv.first)
- {
- parent->_left = cur;
- }
- cur->_parent = parent;
- return true;
- // 更新节点
- while (parent)
- {
- if (cur == parent->_left)
- {
- parent->_bf--;
- }
- else
- {
- parent->_bf++;
- }
- if (parent->_bf == 0)
- {
- break;
- }
- else if (parent->_bf == 1 || parent->_bf == -1)
- {
- cur = parent;
- parent = parent->_parent;
- }
- else if (parent->_bf == 2 || parent->_bf == -2)
- {
- if (parent->_bf == 2 && cur->_bf == 1)
- {
- RotateL(parent);
- }
- else if (parent->_bf == -2 && cur->_bf == -1)
- {
- RotateR(parent);
- }
- else if (parent->_bf == 2 && cur->_bf == -1)
- {
- //右高双旋
- RotateRL(parent);
- }
- else
- {
- //左高双旋
- RotateLR(parent);
- }
-
- }
- else
- {
- assert(false);
- }
- }
- return true;
- }
- void RotateL(Node* parent)
- {
- Node* cur = parent->_right;
- Node* curleft = parent->_left;
- parent->_left = curleft;
- if (curleft)
- {
- curleft->_parent = parent;
- }
- cur->_left = parent;
- Node* ppnode = parent->_parent;
- parent->_parent = cur;
- if (parent == _root)
- {
- _root = cur;
- cur->_parent = nullptr;
- }
- 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;
-
- Node* ppnode = parent->_parent;
- if (curright)
- {
- curright->_parent = parent;
- }
- parent->_parent = cur;
- if (ppnode == _root)
- {
- _root = cur;
- cur->_parent = nullptr;
- }
- else
- {
- if (ppnode->_left == parent)
- {
- ppnode->_left = cur;
- }
- else
- {
- ppnode->_right = cur;
- }
- }
- cur->_bf = parent->_bf = 0;
-
- }
- //右高先右后左
- void RotateRL(Node* parent)
- {
- Node* cur = parent->_right;
- Node* curleft = cur->_left;
- int bf = curleft->_bf;
- RotateR(parent->_right);
- RotateL(parent);
- if (bf == 1)
- {
- cur->_right->_bf = 0;
- cur->_left->_bf= -1;
-
- }
- else if (bf == -1)
- {
- cur->_right->_bf = 0;
- cur->_left->_bf = 1;
- }
- else
- {
- ;
- }
- }
- void RotateLR(Node* parent)
- {
- Node* cur = parent->_left;
- Node* curright = cur->_right;
- int bf = curright->_bf;
- RotateL(cur);
- RotateR(parent);
- if(bf == 1)
- {
- cur->_right->_bf = 0;
- cur->_left->_bf = -1;
-
- }
- else if(bf==-1)
- {
- cur->_right->_bf = 0;
- cur->_left->_bf = 1;
- }
- else
- {
- ;
- }
- }
检验AVL树
- int Height(Node* root)
- {
- if (root == nullptr)
- return true;
- int leftHight = Height(root->_left);
- int right = Height(root->_right);
- return leftHeight > rightHeight ? leftHeight + 1 : rightHeigth + 1;
- }
- bool IsBalance(Node* root)
- {
- if (root == nullptr)
- return true;
- int leftHight = Height(root->_left);
- int rightHight = Height(root->_right);
- if (rightHight-leftHight!=root->_bf)
- {
- cout<<"平衡因子异常"
- }
- return abs(rightHight - leftHight) < 2
- && IsBalance(root->_left)
- && IsBalance(root->_right);
- }