二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。
我们采用三叉链的方式来实现AVL首先我们定义的AVLTreeNode节点如下所示:
template<class K,class V>
struct AVLTreeNode
{
AVLTreeNode<K,V>* _left;
AVLTreeNode<K,V>* _right;
AVLTreeNode<K,V>* _parent;
int _bf;
pair<K, V> _kv;
AVLTreeNode(const pair<K,V>& kv)
:_left(nullptr),
_right(nullptr),
_parent(nullptr),
_bf(0),
_kv(kv)
{
}
};
首先对于AVL树来说,我们这里实现AVLTree的插入实现:当AVL树插入数据时,可以分为以下四种情况 右单旋、左单旋、右左单旋、左右单旋,为了方便记忆我们可以将左、右单旋看成一条直线、右左和左右单旋看成折线。如下所示:
程序实现:
#include<iostream>
#include<assert.h>
using namespace std;
template<class K,class V>
struct AVLTreeNode
{
AVLTreeNode<K,V>* _left;
AVLTreeNode<K,V>* _right;
AVLTreeNode<K,V>* _parent;
int _bf;
pair<K, V> _kv;
AVLTreeNode(const pair<K,V>& kv)
:_left(nullptr),
_right(nullptr),
_parent(nullptr),
_bf(0),
_kv(kv)
{
}
};
template<class K,class V>
class AVLTree
{
typedef AVLTreeNode<K,V> Node;
public:
AVLTree():_root(nullptr)
{
}
void _Destory(Node* root)
{
if (root == nullptr)
return;
_Destory(root->_left);
_Destory(root->_right);
delete root;
}
~AVLTree()
{
_Destory(_root);
_root = nullptr;
}
void _InOrder(Node* root)
{
if (root == nullptr)
return;
_InOrder(root->_left);
cout << root->_kv.first << " ";
_InOrder(root->_right);
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
bool Insert(const pair<K, V>& kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
return true;
}
Node* parent = _root;
Node* cur = _root;
while (cur)
{
if (kv.first > cur->_kv.first)
{
parent = cur;
cur = cur->_right;
}
else if (kv.first < cur->_kv.first)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(kv);
if (parent->_kv.first>kv.first)
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent;
//开始平衡因子的检测 到这从插入的节点往上对平衡因子进行更新
while (cur != _root)
{
if (parent->_right == cur)
{
parent->_bf++;
}
else
{
parent->_bf--;
}
//对更新完后的父亲节点进行检测 分为三种情况
//1、如果parent节点的_bf为0 则跳出
//2、如果parent节点的平衡因子为1或者-1则继续向上更新
//3、如果Parent的节点的平衡因子为-2或者2则不平衡了,应该旋转了
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)
{
//这里开始旋转保持AVLTree的平衡
//旋转分为四种情况
//1、 右单旋
//2、右左单旋
//3、左单旋
//4、左右单旋
//首先要进行右单选时,那么parent->bf==-2时进行右旋
if (parent->_bf == -2)
{
if (cur->_bf == -1)
{
//这里是右单旋
RotateR(parent);
}
else //cur->bf==1 左右双旋转
{
RotateLR(parent);
}
}
else //cur->bf==2
{
if (cur->_bf == 1)
{
RotateL(parent);
}
else
{
RotateRL(parent);
}
}
break;
}
}
return true;
}
void RotateR(Node* parent)
{
Node* SubL = parent->_left;
Node* SubLR = SubL->_right;
parent->_left = SubLR;
if (SubLR)
{
SubLR->_parent = parent;
}
Node* Parentparent = parent->_parent;
SubL->_right = parent;
parent->_parent = SubL;
if (parent == _root)
{
_root = SubL;
_root->_parent = nullptr;
}
else
{
if (Parentparent->_left == parent)
{
Parentparent->_left = SubL;
}
else
{
Parentparent->_right = SubL;
}
SubL->_parent = Parentparent;
}
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* Parentparent = parent->_parent;
if (parent == _root)
{
_root = SubR;
SubR->_parent = nullptr;
}
else
{
if (Parentparent->_left == parent)
{
Parentparent->_left = SubR;
}
else
{
Parentparent->_right = SubR;
}
SubR->_parent = Parentparent;
}
parent->_bf = SubR->_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)
{
SubL->_bf = -1;
parent->_bf = 0;
SubLR->_bf = 0;
}
else if (bf == -1)
{
SubL->_bf = 0;
parent->_bf = 1;
SubLR->_bf = 0;
}
else
{
SubL->_bf = 0;
parent->_bf = 0;
SubLR->_bf = 0;
}
}
void RotateRL(Node* parent)
{
Node* SubR = parent->_right;
Node* SubRL = SubR->_left;
int bf = SubR->_bf;
RotateR(parent->_right);
RotateL(parent);
if (bf == 1)
{
SubR->_bf = 0;
SubRL->_bf = 0;
parent->_bf = -1;
}
else if (bf == -1)
{
parent->_bf = 0;
SubR->_bf = 1;
SubRL->_bf = 0;
}
else
{
parent->_bf = 0;
SubR->_bf = 0;
SubRL->_bf = 0;
}
}
Node* Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (cur->_kv.first < key)
{
cur = cur->_right;
}
else if (cur->_kv.first > key)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return nullptr;
}
int IsHeight(Node* root)
{
if (root == nullptr)
return 0;
int Left=IsHeight(root->_left);
int Right=IsHeight(root->_right);
return Left > Right ? Left + 1 : Right + 1;
}
bool _IsBalance(Node* root)
{
int left = IsHeight(root->_left);
int right = IsHeight(root->_right);
return abs(left - right) < 2;
}
bool IsAVLTree()
{
return _IsBalance(_root);
}
private:
Node* _root;
};
#include"AVLTree.h"
using namespace std;
void Test_AVLTree()
{
//int a[] = { 1, 3, 5, 7, 6 };
//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
//int a[] = { 6,7,8,9,10};
int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
AVLTree<int, int>t;
for (auto e : a)
{
t.Insert(make_pair(e,e));
}
t.InOrder();
}
int main()
{
Test_AVLTree();
return 0;
}