目录
1.AVL树的概念
2.一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
3.AVL树的节点
4.AvL树的插入
1. 按照二叉搜索树的方式插入新节点
2. 调整节点的平衡因子
2.1.右单旋
2.2.左单旋
2.3. 左右双旋
2.4.右左双旋
5.AVL树检测:
6.AVL树的性能
7.最后附上AVL树的全部代码:
因为马上期末考试了/(ㄒoㄒ)/,所以只写了AVL树的插入详细解法,但质量绝对保证包看包会,等期末之后更新AVL树的删除操作!!!
#include
#include
using namespace std;
template
struct AVL_NODE
{
AVL_NODE(const T &value=T())
:_parent(nullptr),_left(nullptr),_right(nullptr),val(value),bf(0)
{}
AVL_NODE* _parent;
AVL_NODE* _left;
AVL_NODE* _right;
T val;
int bf;//平衡因子
};
template
class AVL_Tree
{
typedef AVL_NODE Node;
public:
AVL_Tree()
:_root(nullptr)
{}
~AVL_Tree()
{}
bool Insert(const T& value)
{
if (_root == nullptr)
{
_root = new Node(value);
return true;
}
else
{
Node* parent = nullptr;
Node* cur = _root;
while (cur!=nullptr)
{
parent = cur;
if (cur->val > value)
{
cur = cur->_left;
}
else if(cur->val_right;
}
else
{//不可以插入相同的val的节点
return false;
}
}
cur = new Node(value);
if (parent->val < value)
{
parent->_right =cur ;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;
//更新平衡因子:
while (parent)
{
//如果插入节点插入在当前节点的左子树那么我们我们将其父节点的平衡因子--
if (cur == parent->_left)
{
parent->bf--;
}
else
{
parent->bf++;
}
//如果当前父节点的平衡因子经过更新为0,那么它对上面的节点的平衡因子是没有影响的直接退出循环
if (parent->bf == 0)
{
break;
}
//如果当前的父节点的平衡因子更新为-1或者1那么它就会对在他之前的平衡因子产生影响则继续更新上面的平衡因子
else if (parent->bf == 1 || parent->bf == -1)
{
cur = parent;
parent = cur->_parent;
}
//最后一种情况就是更新之后平衡因子为-2或者+2失衡了那么我们就需要对当前的节点进行旋转操作,然后调整更新
//经过调整后的节点的平衡因子
else
{
//更新平衡因子
if (parent->bf == -2)
{//这里如果parent的平衡因子为-2那么节点一定插在当前树的较高左子树
if (cur->bf == -1)
{//cur==-1,那么节点就是插在了cur的外侧那么我们要右旋
RotateR(parent);
}
else if (cur->bf == 1)
{//cur==1,节点插入在cur的内侧那么我们要左右双旋
RotateLR(parent);
}
}
if (parent->bf == 2)
{//这里如果parent的平衡因子我们2那么节点一定插入在当前树的较高右子树
if (cur->bf == 1)
{//cur->bf==1,那么节点插入到了cur的外侧也就是右侧我们要左单旋转
RotateL(parent);
}
else if (cur->bf == -1)
{//cur->bf==-1,那么节点插入到了cur的内测也就是左侧我们需要右左双旋
RotateRL(parent);
}
}
break;
}
}
}
}
//中序遍历:
void InOrder()
{
cout << "中序遍历结果:";
mid(_root);
cout << endl;
}
//判断是否是AVL树
bool IsValidAVLTree()
{
return _IsValidAVLTree(_root);
}
private:
//获取树的高度
int GetHeight(Node* root)
{
if (nullptr == root)
return 0;
int leftHeight = GetHeight(root->_left);
int rightHeight = GetHeight(root->_right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
//判断是否是AVL树
bool _IsValidAVLTree(Node* root)
{
if (nullptr == root)
return true;
// 根节点
int leftHegiht = GetHeight(root->_left);
int rigthHegiht = GetHeight(root->_right);
if (rigthHegiht - leftHegiht != root->bf || abs(root->bf) > 1)
{
cout << "Node:" << root->val << endl;
cout << rigthHegiht - leftHegiht << " " << root->bf << endl;
return false;
}
// 根的左子树 和 根的右子树组成
return _IsValidAVLTree(root->_left) &&
_IsValidAVLTree(root->_right);
}
//中序遍历
void mid(Node* root)
{
if (root == nullptr)
{
return;
}
mid(root->_left);
cout << root->val <<" ";
mid(root->_right);
}
//右单旋:用于插入较高左子树的左边节点
void RotateR(Node* parent)
{
Node* subL = parent->_left;//将当前失衡节点的较高左子树保存
Node* subLR = subL->_right;//将较高左子树的右节点保存
Node* pparent = parent->_parent;//将当前失衡节点的parent保存
parent->_left = subLR;//将parent的左连到当前左子树的右节点
//如果subLR存在那么将其父节点更新
if (subLR)
{
subLR->_parent = parent;
}
//将parent右旋下来:
subL->_right = parent;
//parent旋下来就要更新parent的父节点
parent->_parent = subL;
//此时subL就要更新父节点
subL->_parent = pparent;
if (pparent)
{
if (parent == pparent->_right)
{
pparent->_right = subL;
}
else
{
pparent->_left = subL;
}
}
else
{//如果pparent不存在那么就将根节点更新为subL
_root = subL;
}
//更新节点的平衡因子一共分为四种情况:
//1.当前节点有右孩子,父亲节点有右孩子:
//2.当前节点有右孩子,父亲节点没有右孩子:不可能有这种情况
//3.当前节点没有右孩子,父亲节点有右孩子,是没有这种情况的,这种情况就和第四种情况类似因为如果当前节点没有右孩子,
//然后在插入一个左孩子那么当前的节点本身就不平衡了就需要调整
//4.当前节点没有右孩子,父亲节点没有右孩子
//第一种和第四种情况一样都是直接将subL和parent的平衡因子更新为0
subL->bf = parent->bf = 0;
}
//左单旋:用于节点插入较高右子树的右边:
void RotateL(Node* parent)
{
Node* subR = parent->_right;//将当前失衡节点的较高右子树保存
Node* subRL = subR->_left;//将较高右子树的左节点保存
Node* pparent = parent->_parent;//将当前失衡节点的parent保存
parent->_right = subRL;//将parent的右连到当前右子树的左节点
//如果subRL存在那么将其父节点更新
if (subRL)
{
subRL->_parent = parent;
}
//将parent右旋下来:
subR->_left = parent;
//parent旋下来就要更新parent的父节点
parent->_parent = subR;
//此时subR就要更新父节点
subR->_parent = pparent;
if (pparent)
{
if (parent == pparent->_right)
{
pparent->_right = subR;
}
else
{
pparent->_left = subR;
}
}
else
{//如果pparent不存在那么就将根节点更新为subL
_root = subR;
}
//更新各节点的平衡因子
subR->bf = parent->bf = 0;
}
void RotateLR(Node* parent) {
Node* subL = parent->_left;
Node* subLR = subL->_right;
// 旋转之前,保存subLR的平衡因子,旋转完成之后,需要根据该平衡因子来调整其他节点的平衡因子
int _bf = subLR->bf;
// subL进行左单旋
RotateL(parent->_left);
// 再对parent进行右单旋
RotateR(parent);
if (1 == _bf)
subL->bf = -1;
else if (-1 == _bf)
parent->bf = 1;
}
//新节点插入较高右子树的左侧(内测)--- 右左:先右单旋再左单旋
void RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
//保存subRL的平衡因子,旋转完成之后根据该平衡因子来调整其他节点的平衡因子
int bf = subRL->bf;
RotateR(parent->_right);
RotateL(parent);
if(bf==1)
{
parent->bf = -1;
}
else if(-1==bf)
{
subR->bf = 1;
}
}
Node* _root;
};
int main()
{
AVL_Tree t;
//vector v = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
vector v = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
for (int a:v)
{
t.Insert(a);
}
t.InOrder();
if (t.IsValidAVLTree())
cout << "t is valid AVLTree" << endl;
else
cout << "t is invalid AVLTree" << endl;
return 0;
}