G. M. Adelson-Velsky和E. M. Landis两位数学家在1962年发明了自平衡二叉搜索树,计算机科学界从此进入了数据高速存储和检索的时代。
template<class KEY, class VALUE>
struct AVLTreeNode
{
AVLTreeNode<KEY, VALUE>* _pleft;
AVLTreeNode<KEY, VALUE>* _pright;
AVLTreeNode<KEY, VALUE>* _pParent; //前驱指针
//key_value键值对(KEY用于搜索,VALUE用于存储数据)
pair<KEY, VALUE> _key_value;
//以该节点为根节点的子树的平衡因子
int _balanceFactor;
//结点构造函数
AVLTreeNode(const pair<KEY, VALUE>& pairdata)
: _pleft(nullptr),
_pright(nullptr),
_pParent(nullptr),
_key_value(pairdata),
_balanceFactor(0)
{}
};
AVL树的节点插入算法在二叉搜索树的节点插入算法的基础上增加了平衡因子的更新与平衡化的操作
//插入节点并更新树的平衡因子,并判断是否要执行旋转
bool insert(const Pair& KEYVALUE)
{
if (_root == nullptr)
{
_root = new Node(KEYVALUE);
return true;
}
Node* cur = _root;
Node* parent = nullptr;
//查找插入的位置
while (cur != nullptr)
{
if (cur->_key_value.first < KEYVALUE.first)
{
parent = cur;
cur = cur->_pright;
}
else if (cur->_key_value.first > KEYVALUE.first)
{
parent = cur;
cur = cur->_pleft;
}
else
{
//KEY值重复,无法插入
return false;
}
}
//找到空位置执行插入
cur = new Node(KEYVALUE);
if (parent->_key_value.first < KEYVALUE.first)
{
//向右孩子插入
parent->_pright = cur;
cur->_pParent = parent;
}
else
{
parent->_pleft = cur;
cur->_pParent = parent;
}
}
//插入的节点在叶子位置,只有该叶子节点所在的连通路径上的节点的平衡因此会受影响
//完成节点插入后更新平衡因子(沿着连通路径自底向上向上更新平衡因子)
while (parent)
{
if (parent->_pright == cur)
{
//右子树高度加一,平衡因子加一
parent->_balanceFactor++;
}
else
{
//左子树高度加一,平衡因子减一
parent->_balanceFactor--;
}
//根据调整后parent的平衡因子,判断是否需要旋转或继续回溯调整祖先的平衡因子
//parent的平衡因子变为0说明左右子树在插入节点后高度相同,则子树的高度没有变化,无须再回溯调整
if (parent->_balanceFactor == 0)
{
break;
}
//parent的平衡因子变为1或-1说明原来parent的平衡因子为0,此时树的高度增加了1,需要继续向上调整祖先的平衡因子
//[以前驱节点为树根的子树的平衡因子受当前子树的高度的影响(呈递推关系)]
else if (parent->_balanceFactor == -1
|| parent->_balanceFactor == 1)
{
cur = parent;
parent = parent->_pParent;
}
//parent的平衡因子变为2或-2,插入节点后子树失衡,需要平衡化处理
else if (parent->_balanceFactor == -2
|| parent->_balanceFactor == 2)
{
//平衡化算法
}
//AVL树出现不合法情况,报错终止程序(AVL树插入节点后不可能出现平衡因子大于2的结点)
else
{
assert(false);
return false;
}
}
//左单旋成员接口
void _RotationSL(Node* parent)
{
//整个子结构的祖先(可能为空,即parent就是整棵树的树根)
Node* Graparent = parent->_pParent;
Node* parentR = parent->_pright;
//parentR的左子树(可能为空)
Node* parentRLSon = parentR->_pleft;
//左单旋
parent->_pright = parentRLSon;
//注意parentLSon可能为空
if (parentRLSon)
{
parentRLSon->_pParent = parent;
}
parentR->_pleft = parent;
parent->_pParent = parentR;
//注意GGraparent可能为空
if (Graparent)
{
if (Graparent->_pleft == parent)
{
Graparent->_pleft = parentR;
}
else
{
Graparent->_pright = parentR;
}
}
else
{
_root = parentR;
}
parentR->_pParent = Graparent;
//调整平衡因子
parent->_balanceFactor = 0;
parentR->_balanceFactor = 0;
}
//右单旋成员接口
void _RotationSR(Node* parent)
{
Node* Graparent = parent->_pParent;
Node* parentL = parent->_pleft;
Node* parentLRSon = parentL->_pright;
//右单旋
parent->_pleft = parentLRSon;
if (parentLRSon)
{
parentLRSon->_pParent = parent;
}
parentL->_pright = parent;
parent->_pParent = parentL;
if (Graparent)
{
if (Graparent->_pleft == parent)
{
Graparent->_pleft = parentL;
}
else
{
Graparent->_pright = parentL;
}
}
else
{
_root = parentL;
}
parentL->_pParent = Graparent;
//更新平衡因子
parentL->_balanceFactor = 0;
parent->_balanceFactor = 0;
}
//左右双旋接口
void _RotationDLR(Node* parent)
{
Node* parentL = parent->_pleft;
Node* parentLRSon = parentL->_pright;
int _balancefactorOfparentLRSon = parentLRSon->_balanceFactor;
//先执行左单旋操作
_RotationSL(parentL);
//再执行右单旋操作
_RotationSR(parent);
//完成单旋后分三种情形更新平衡因子(根据parentLRSon的双旋前的平衡因子可以区分三种情况)
parentLRSon->_balanceFactor = 0;
if (_balancefactorOfparentLRSon == 1)
{
parent->_balanceFactor = 0;
parentL->_balanceFactor = -1;
}
else if (_balancefactorOfparentLRSon == -1)
{
parent->_balanceFactor = 1;
parentL->_balanceFactor = 0;
}
else if (_balancefactorOfparentLRSon == 0)
{
parent->_balanceFactor = 0;
parentL->_balanceFactor = 0;
}
//出现其他情形则说明数据结构不合法
else
{
assert(false);
}
}
//右左双旋接口
void _RotationDRL(Node* parent)
{
Node* parentR = parent->_pright;
Node* parentRLSon = parentR->_pleft;
int balancefactorOfparentRLSon = parentRLSon->_balanceFactor;
//执行右单旋
_RotationSR(parentR);
//执行左单旋
_RotationSL(parent);
//更新平衡因子
parentRLSon->_balanceFactor = 0;
if (balancefactorOfparentRLSon == 1)
{
parent->_balanceFactor = -1;
parentR->_balanceFactor = 0;
}
else if (balancefactorOfparentRLSon == -1)
{
parent->_balanceFactor = 0;
parentR->_balanceFactor = 1;
}
else if (balancefactorOfparentRLSon == 0)
{
parent->_balanceFactor = 0;
parentR->_balanceFactor = 0;
}
else
{
assert(false);
}
}
#include
#include
#include
using std::pair;
using std::max;
using std::make_pair;
template<class KEY, class VALUE>
struct AVLTreeNode
{
AVLTreeNode<KEY, VALUE>* _pleft;
AVLTreeNode<KEY, VALUE>* _pright;
AVLTreeNode<KEY, VALUE>* _pParent; //前驱指针
//key_value键值对(KEY用于搜索,VALUE用于存储数据)
pair<KEY, VALUE> _key_value;
//以该节点为根节点的子树的平衡因子
int _balanceFactor;
//结点构造函数
AVLTreeNode(const pair<KEY, VALUE>& pairdata)
: _pleft(nullptr),
_pright(nullptr),
_pParent(nullptr),
_key_value(pairdata),
_balanceFactor(0)
{}
};
template <class KEY, class VALUE>
class AVLTree
{
//重命名结点并实例化节点模版
typedef AVLTreeNode<KEY, VALUE> Node;
//重命名结点并实例化键值对模版
typedef pair<KEY, VALUE> Pair;
public:
AVLTree<KEY, VALUE>()
:_root(nullptr)
{
;
}
//插入节点并更新树的平衡因子,并判断是否要执行旋转
bool insert(const Pair& KEYVALUE)
{
if (_root == nullptr)
{
_root = new Node(KEYVALUE);
return true;
}
Node* cur = _root;
Node* parent = nullptr;
//查找插入的位置
while (cur != nullptr)
{
if (cur->_key_value.first < KEYVALUE.first)
{
parent = cur;
cur = cur->_pright;
}
else if (cur->_key_value.first > KEYVALUE.first)
{
parent = cur;
cur = cur->_pleft;
}
else
{
//KEY值重复,无法插入
return false;
}
}
//找到空位置执行插入
cur = new Node(KEYVALUE);
if (parent->_key_value.first < KEYVALUE.first)
{
//向右孩子插入
parent->_pright = cur;
cur->_pParent = parent;
}
else
{
parent->_pleft = cur;
cur->_pParent = parent;
}
//插入的节点在叶子位置,只有该叶子节点所在的连通路径上的节点的平衡因此会受影响
//完成节点插入后更新平衡因子(沿着连通路径自底向上向上更新平衡因子)
while (parent)
{
if (parent->_pright == cur)
{
//右子树高度加一,平衡因子加一
parent->_balanceFactor++;
}
else
{
//左子树高度加一,平衡因子减一
parent->_balanceFactor--;
}
//根据调整后parent的平衡因子,判断是否需要旋转或继续回溯调整祖先的平衡因子
//parent的平衡因子变为0说明左右子树在插入节点后高度相同,则子树的高度没有变化,无须再回溯调整
if (parent->_balanceFactor == 0)
{
break;
}
//parent的平衡因子变为1或-1说明原来parent的平衡因子为0,此时树的高度增加了1,需要继续向上调整祖先的平衡因子
//[以前驱节点为树根的子树的平衡因子受当前子树的高度的影响(呈递推关系)]
else if (parent->_balanceFactor == -1 || parent->_balanceFactor == 1)
{
cur = parent;
parent = parent->_pParent;
}
//parent的平衡因子变为2或-2,插入节点后子树失衡,需要执行旋转
else if (parent->_balanceFactor == -2 || parent->_balanceFactor == 2)
{
//执行左单旋
if (parent->_balanceFactor == 2 && cur->_balanceFactor == 1)
{
_RotationSL(parent);
//旋转完后子结构平衡因子变为0,无需继续调整向上调整平衡因子
break;
}
//执行右单旋
else if (parent->_balanceFactor == -2 && cur->_balanceFactor == -1)
{
_RotationSR(parent);
//旋转完后子结构平衡因子变为0,无需继续调整向上调整平衡因子
break;
}
//执行左右双旋
else if (parent->_balanceFactor == -2 && cur->_balanceFactor == 1)
{
_RotationDLR(parent);
break;
}
//执行右左双旋
else if (parent->_balanceFactor == 2 && cur->_balanceFactor == -1)
{
_RotationDRL(parent);
break;
}
//如果出现其他情况则说明数据结构异常报错即可
else
{
assert(false);
}
}
//AVL树出现不合法情况,报错终止程序(AVL树插入节点后不可能出现平衡因子大于2的结点)
else
{
assert(false);
return false;
}
}
return true;
}
void Inorder()
{
_Inoder(_root);
}
//判断树是否平衡
bool isBalanced()
{
return _CountHeight(_root) != -1;
}
private:
//左单旋成员接口
void _RotationSL(Node* parent)
{
//整个子结构的祖先(可能为空,即parent就是整棵树的树根)
Node* Graparent = parent->_pParent;
Node* parentR = parent->_pright;
//parentR的左子树(可能为空)
Node* parentRLSon = parentR->_pleft;
//左单旋
parent->_pright = parentRLSon;
//注意parentLSon可能为空
if (parentRLSon)
{
parentRLSon->_pParent = parent;
}
parentR->_pleft = parent;
parent->_pParent = parentR;
//注意GGraparent可能为空
if (Graparent)
{
if (Graparent->_pleft == parent)
{
Graparent->_pleft = parentR;
}
else
{
Graparent->_pright = parentR;
}
}
else
{
_root = parentR;
}
parentR->_pParent = Graparent;
//调整平衡因子
parent->_balanceFactor = 0;
parentR->_balanceFactor = 0;
}
//右单旋成员接口
void _RotationSR(Node* parent)
{
Node* Graparent = parent->_pParent;
Node* parentL = parent->_pleft;
Node* parentLRSon = parentL->_pright;
//右单旋
parent->_pleft = parentLRSon;
if (parentLRSon)
{
parentLRSon->_pParent = parent;
}
parentL->_pright = parent;
parent->_pParent = parentL;
if (Graparent)
{
if (Graparent->_pleft == parent)
{
Graparent->_pleft = parentL;
}
else
{
Graparent->_pright = parentL;
}
}
else
{
_root = parentL;
}
parentL->_pParent = Graparent;
//更新平衡因子
parentL->_balanceFactor = 0;
parent->_balanceFactor = 0;
}
//左右双旋接口
void _RotationDLR(Node* parent)
{
Node* parentL = parent->_pleft;
Node* parentLRSon = parentL->_pright;
int _balancefactorOfparentLRSon = parentLRSon->_balanceFactor;
//先执行左单旋操作
_RotationSL(parentL);
//再执行右单旋操作
_RotationSR(parent);
//完成单旋后分三种情形更新平衡因子(根据parentLRSon的双旋前的平衡因子可以区分三种情况)
parentLRSon->_balanceFactor = 0;
if (_balancefactorOfparentLRSon == 1)
{
parent->_balanceFactor = 0;
parentL->_balanceFactor = -1;
}
else if (_balancefactorOfparentLRSon == -1)
{
parent->_balanceFactor = 1;
parentL->_balanceFactor = 0;
}
else if (_balancefactorOfparentLRSon == 0)
{
parent->_balanceFactor = 0;
parentL->_balanceFactor = 0;
}
//出现其他情形则说明数据结构不合法
else
{
assert(false);
}
}
//右左双旋接口
void _RotationDRL(Node* parent)
{
Node* parentR = parent->_pright;
Node* parentRLSon = parentR->_pleft;
int balancefactorOfparentRLSon = parentRLSon->_balanceFactor;
//执行右单旋
_RotationSR(parentR);
//执行左单旋
_RotationSL(parent);
//更新平衡因子
parentRLSon->_balanceFactor = 0;
if (balancefactorOfparentRLSon == 1)
{
parent->_balanceFactor = -1;
parentR->_balanceFactor = 0;
}
else if (balancefactorOfparentRLSon == -1)
{
parent->_balanceFactor = 0;
parentR->_balanceFactor = 1;
}
else if (balancefactorOfparentRLSon == 0)
{
parent->_balanceFactor = 0;
parentR->_balanceFactor = 0;
}
else
{
assert(false);
}
}
//中序遍历
void _Inoder(Node* root)
{
if (nullptr == root)
{
return;
}
_Inoder(root->_pleft);
std::cout << root->_key_value.first << ' ';
_Inoder(root->_pright);
}
//判断树是否平衡
int _CountHeight(Node* root)
{
if (nullptr == root)
{
return 0;
}
int leftheight = _CountHeight(root->_pleft);
int rightheight = (leftheight == -1) ? -1 : _CountHeight(root->_pright);
std::cout << "CheckFactor : " << (root->_balanceFactor == (rightheight - leftheight)) << std::endl;
std::cout << "Factor:" << root->_balanceFactor << std::endl;
if (abs(leftheight - rightheight) >= 2 || leftheight == -1 || rightheight == -1)
{
return -1;
}
return max(leftheight, rightheight) + 1;
}
private:
Node* _root = nullptr;
};