什么是AVL树
首先AVL树是二叉搜索树,但是严格的控制高度,因为如果插入树的序列原本就是有序的,那二叉搜索树就近似于链表,查找效率极其低下,所以就引入AVL树并且满足下列条件。
- 每个结点左右子树高度差不超过 1
- 左右子树仍然满足上述条件
由于严格的控制高度,所以AVL树的查找效率还是 O(log2N),如果有N个结点,就会把树的高度控制在O(log2N)
AVL树的插入
首先按照二叉搜索树的插入方式进行插入(如果为空直接插入作根节点,如果不为空,比当前结点大就到左子树,比当前结点小就到右子树,在合适的位置插入),然后更新平衡因子,如果平衡因子变为了 2 或者 -2,就对树进行旋转处理
- 当新插入结点在较高左子树的左侧,进行右单旋转
- 当新插入的结点在较高右子树的右侧,进行左单旋转
- 当新插入的结点在较高左子树的右侧,进行左右双旋
- 当新插入的结点在较高右子树的左侧,进行右左双旋
旋转完成之后还要更新所旋转的结点的平衡因子
插入结点的实现
bool insert(const pair<K,V>& kv) {
// 1.如果根不存在,直接让新结点作为根
if (_root == nullptr) {
_root = new Node(kv);
return true;
}
// 按照二叉搜索树的方式插入
Node* parent = nullptr;
Node* cur = _root;
while (cur) {
if (cur && cur->_kv.first > kv.first) {
parent = cur;
cur = cur->_left;
}
else if (cur && cur->_kv.first <= kv.first) {
parent = cur;
cur = cur->_right;
}
else {
return false;
}
}
cur = new Node(kv);
if (parent->_kv.first > kv.first) {
parent->_left = cur;
cur->_parent = parent;
}
else {
parent->_right = cur;
cur->_parent = parent;
}
// 2.更新平衡因子
while (parent) {
if (cur == parent->_right) {
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) {
// 新结点插入在较高右子树的右侧:右右 -- 左旋
if (cur->_bf == 1) {
RotateL(parent);
}
// 新结点插入在较高右子树的左侧:右左 -- 右左双旋
else if (cur->_bf == -1) {
RotateRL(parent);
}
}
else if (parent->_bf == -2) {
// 新结点插入在较高左子树的左侧:左左 -- 右旋
if (cur->_bf == -1) {
RotateR(parent);
}
// 新结点插入在较高左子树的右侧:左右 -- 左右双旋
else if (cur->_bf == 1) {
RotateLR(parent);
}
}
// 旋转完成后,parent的高度就恢复到插入之前的高度,更新结束
break;
}
}
return true;
}
// 左旋
void RotateL(Node *parent) {
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if(subRL)
subRL->_parent = parent;
subR->_left = parent;
Node* ppNode = parent->_parent;
parent->_parent = subR;
// 1.如果parent是原来这棵树的根,那么现在 subR 是根
// 2.如果不是根,让subR顶替原来parent的位置
if (parent == _root) {
_root = subR;
subR->_parent = nullptr;
}
else if (parent == ppNode->_right) {
ppNode->_right = subR;
subR->_parent = ppNode;
}
else if (parent == ppNode->_left) {
ppNode->_left = subR;
subR->_parent = ppNode;
}
parent->_bf = subR->_bf = 0;
}
void RotateR(Node* parent) {
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
subL->_right = parent;
Node* ppNode = parent->_parent;
parent->_parent = subL;
if (parent == _root) {
_root = subL;
subL->_parent = nullptr;
}
else if (parent == ppNode->_right) {
ppNode->_right = subL;
subL->_parent = ppNode;
}
else if (parent == ppNode->_left) {
ppNode->_left = subL;
subL->_parent = ppNode;
}
parent->_bf = subL->_bf = 0;
}
void RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf;
RotateR(parent->_right);
RotateL(parent);
if (bf == -1) {
parent->_bf = 0;
subR->_bf = 1;
subRL->_bf = 0;
}
else if (bf == 1) {
subR->_bf = 0;
parent->_bf = -1;
subRL->_bf = 0;
}
else if (bf == 0) {
subR->_bf = 0;
parent->_bf = 0;
subRL->_bf = 0;
}
}
void RotateLR(Node* parent) {
Node* subL = parent->_left;
Node* subLR = subL->_right;
int bf = subLR->_bf;
RotateL(subL);
RotateR(parent);
if (bf == 1) {
parent->_bf = 0;
subL->_bf = -1;
subLR->_bf = 0;
}
else if (bf == -1) {
parent->_bf = 1;
subL->_bf = 0;
subLR->_bf = 0;
}
else if (bf == 0) {
parent->_bf = 0;
subL->_bf = 0;
subLR->_bf = 0;
}
}