1.什么是AVL树
AVL树就是在搜索二叉树的基础上通过控制左右子树的高度差实现的,在搜索二叉树的基础上,通过旋转来控制,是左右子树高度差的绝对值严格控制为不超过1(通过旋转来控制树的高度)。由于搜索二叉树的效率最差为O(N-1)次,(n为节点个数),所以为了减少查找时间而创造了AVL树,
当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。
2.AVL树的定义
一颗AVL树或者是空树,是具有以下性质的树:
1.他的左右子树都是AVL树
2.左右高度差的绝对值不超过1(即1,0,-1)
如果一棵二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结点,其高度可保持在
O(log_2 n),搜索时间复杂度O(log_2 n)。AVL树就是在二叉搜索树的基础上引入了平衡因子,因此AVL树也可以看成是二叉搜索树。那么,AVL树的插入过程可以分为两步:
1. 按照二叉搜索树的方式插入新节点
2. 调整节点的平衡因子
标准AVL树
3. AVL树的实现
AVL树最重要的就是旋转,需要控制左右子树高度差的绝对值不超过1,因此,平衡因子可能存在三种情况,即0,正负1,正负2,
1. 如果平衡因子为0,说明插入之前pParent的平衡因子为正负1,插入后被调整成0,此时满足AVL树的性质,插入成功
2. 如果平衡因子为正负1,说明插入前pParent的平衡因子一定为0,插入后被更新成正负1,此时以pParent为根的树的高度增加,需要继续向上更新。
3. 如果pParent的平衡因子为正负2,则pParent的平衡因子违反平衡树的性质,需要对其进行旋转处理。
如果在一棵原本是平衡的AVL树中插入一个新节点,可能造成不平衡,此时必须调整树的结构,
使之平衡化。根据节点插入位置的不同,AVL树的旋转分为四种:
1.新节点插入较高左子树的左侧---左左:右单旋
2.新插入节点较高右子树的右侧:左旋转
3.新节点插入较高左子树的右侧---左右:先左单旋再右单旋
4.. 新节点插入较高右子树的左侧---右左:先右单旋再左单旋
4.代码实现
#pragma once
#include <iostream>
#include <assert.h>
using namespace std;
namespace _3s
{
template<class K, class V>
struct AVLTreeNode
{
AVLTreeNode* _left;
AVLTreeNode* _right;
AVLTreeNode* _parent;
std::pair<K, V> _KV;
int bf;
AVLTreeNode(const std::pair<K, V> kv)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _KV(kv)
, bf(0)
{}
};
//节点
template<class K, class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
//插入
bool insert(const std::pair<K, V>& kv)
{
if (root == nullptr)
{
root = new Node(kv);
return true;
}
Node* parent = nullptr;
Node* cur = root;
while (cur)
{
if (cur->_left.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_left.first > kv.first)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(kv);
if (parent->_kv.first > kv.first)
{
parent->left = cur;
parent->bf--;
}
else
{
parent->right = cur;
parent->bf++;
}
cur->_parent = parent;
while (parent)
{
if (abs(parent->bf) == 1)
{
parent = parent->_parent;
cur = cur->_parent;
}
else if (abs(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)
{
RotateLR(parent);
}
break;
}
else
{
assert(false);
}
}
return true;
}
private:
//左旋转
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
Node* ppNode = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (root == parent)
{
root = subR;
subR->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subR;
}
else
{
ppNode->_right = subR;
}
subR->_parent = ppNode;
}
subR->_bf = parent->_bf = 0;
}
//右旋转
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subR->_right;
parent->_left = subRL;
if (subRL)
subRL->_parent = parent;
Node* ppNode = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
if (root == parent)
{
root = subL;
subL->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subR->_parent = ppNode;
}
subL->_bf = parent->_bf = 0;
}
//左右旋转
void RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
int _bf = subLR->bf;
RotateL(parent->_left);
RotateR(parent);
subLR->bf = 0;
if (_bf == 1)
{
parent->_bf = 0;
subL->_bf = -1;
}
else if (_bf == -1)
{
parent->bf = 1;
subL->bf = 0;
}
else if (_bf == 0)
{
parent->bf = 0;
subL->bf = 0;
}
else
{
assert(false);
}
}
//右左旋转
void RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subL->_left;
int _bf = subLR->bf;
RotateR(parent->_right);
RotateL(parent);
subRL->_bf = 0;
if (bf == 1)
{
subR->_bf = 0;
parent->_bf = -1;
}
else if (bf == -1)
{
subR->_bf = 1;
parent->_bf = 0;
}
else if (bf == 0)
{
parent->_bf = 0;
subR->_bf = 0;
}
else
{
assert(false);
}
}
private:
Node* root = nullptr;
};
}