一、定义
AVL树即高度平衡二叉搜索树,这里的高度指树的高度。
需要引入一个新的概念——平衡因子,一个节点的平衡因子等于其右子树高度-左子树高度的值。
AVL树的各节点的平衡因子只能属于0、-1、1三种情况。
二、结构
AVL树的实现需要使用三叉链,除了定义_left、_right外,还需要定义_parent,用于记录节点的父亲节点。同时平衡因子定义为int _bf。
三、节点插入对_bf的影响
分两种情况,其一,cur插入到parent的左边,parent的_bf--;其二,cur插入到parent的右边,parent的_bf++。
四、_bf更新后的处理
1.parent更新后的_bf==0的话,说明parent子树的高度没有发生变化,不再继续往上更新_bf。
2.parent更新后的|_bf|==1时,说明parent子树的高度发生变化,需要继续往上更新_bf。
3.parent更新后的|_bf|==2时,说明子树已经不平衡,不再更新_bf,需要旋转以求平衡。
五、旋转
1.左单旋
2.右单旋
3.右左双旋
4.左右双旋
六、需要旋转的情况
1.parent->_bf==2&&cur->_bf==1 需要进行左单旋
2.parent->_bf==-2&&cur->_bf==-1 需要进行右单旋
3.parent->_bf==2&&cur->_bf==-1 需要进行右左双旋
4.parent->_bf==-2&&cur->_bf==1 需要进行左右双旋
七、代码
以左单旋为例:
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;
if (_root == parent) //判断parent的上面是否还有节点,并做出处理
{
_root = subR;
subR->_parent = NULL;
}
else
{
if (ppNode->_right == parent)
{
ppNode->_right = subR;
}
else
{
ppNode->_left = subR;
}
subR->_parent = ppNode;
}
}
八、完整代码
#pragma once
template<class K,class V>
struct AVLTreeNode
{
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;
K _key;
V _value;
int _bf; //平衡因子
AVLTreeNode(const K& key, const V& value) //构造函数
:_key(key)
, _value(value)
, _left(NULL)
, _right(NULL)
, _parent(NULL)
, _bf(0)
{}
};
template<class K,class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
AVLTree()
:_root(NULL)
{}
bool Insert(const K& key, const V& value)
{
if (_root == NULL)
{
_root = new Node(key, value);
return true;
}
Node* cur = _root;
Node* parent = NULL;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key>key)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(key, value);
if (parent->_key < key)
{
parent->_right = cur;
cur->_parent = parent;
}
else
{
parent->_left = cur;
cur->_parent = parent;
}
//更新平衡因子
//如果不平衡,进行旋转
while (parent) //parent_bf==0时不需要更新,所以当parent不为0时更新
{
if (cur == parent->_right)
{
parent->_bf++;
}
else
{
parent->_bf--;
}
if (parent->_bf == 1 || parent->_bf == -1) //直接向上更新
{
cur = parent;
parent = cur->_parent;
}
else
{
//旋转以求平衡
if (parent->_bf == -2)
{
if (cur->_bf == -1) //右单旋
{
RotateR(parent);
}
else //cur->_bf==1
{
RotateLR(parent);
}
}
else if(parent->_bf==2)
{
if (cur->_bf == 1) //左单旋
{
RotateL(parent);
}
else //cur->_bf==-1
{
RotateRL(parent);
}
}
break; //旋转后平衡,直接break
} //end旋转
} //end平衡因子的更新和失衡处理
return true;
}
void RotateR(Node* parent) //右单旋
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
//将subLR链到parent的左边
parent->_left = subLR;
if (subLR)
{
subLR->_parent = parent;
}
//将parent链到subL的右边,并记录下原始parent的parent
subL->_right = parent;
Node* ppNode = parent->_parent;
parent->_parent = subL;
//判断parent之前是不是根节点,并由此给出相应处理
if (ppNode == NULL) //parent是根节点,或parent等于_root
{
_root = subL;
subL->_parent = NULL;
}
else //parent不是根节点
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
subL->_bf = parent->_bf = 0;
}
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;
if (_root == parent) //判断parent的上面是否还有节点,并做出处理
{
_root = subR;
subR->_parent = NULL;
}
else
{
if (ppNode->_right == parent)
{
ppNode->_right = subR;
}
else
{
ppNode->_left = subR;
}
subR->_parent = ppNode;
}
subR->_bf = parent->_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 = -1;
subR->_bf = 0;
}
else if (bf == -1)
{
parent->_bf = 0;
subR->_bf = 1;
}
else //bf==0
{
subR->_bf = parent->_bf = 0;
}
subRL->_bf = 0;
}
void RotateLR(Node* parent) //左右双旋
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
int bf = subLR->_bf;
RotateL(parent->_left);
RotateR(parent);
if (bf == -1)
{
parent->_bf = 1;
subL->_bf = 0;
}
else if (bf == 1)
{
parent->_bf = 0;
subL->_bf = -1;
}
else
{
subL->_bf = parent->_bf = 0;
}
subLR->_bf = 0;
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
void _InOrder(Node* root)
{
if (root == NULL)
{
return;
}
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
bool IsBlance() //为了便于测试程序,设置检查平衡因子的函数
{
return _IsBlance(_root);
}
bool _IsBlance(Node* root)
{
if (root == NULL)
{
return true;
}
int left = Height(root->_left);
int right = Height(root->_right);
if ((right - left) != root->_bf ||( abs(right - left) >= 2)) //abs取绝对值
{
cout << "平衡因子异常" << root->_key << endl;
return false;
}
return _IsBlance(root->_left) && _IsBlance(root->_right);
}
int Height(Node* root)
{
if (root == NULL)
{
return 0;
}
int left = Height(root->_left);
int right = Height(root->_right);
return left > right ? left + 1 : right + 1;
}
protected:
Node* _root;
};
void TestAVLTree()
{
AVLTree<int, int> t;
int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); i++)
{
t.Insert(a[i], i);
}
t.InOrder();
cout << "是否平衡? " << t.IsBlance() << endl;
AVLTree<int, int> t1;
int a1[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
for (size_t i = 0; i < sizeof(a1) / sizeof(a1[0]); i++)
{
t1.Insert(a1[i], i);
}
t1.InOrder();
cout << "是否平衡? " << t1.IsBlance() << endl;
}