目录
logn
基本概念
旋转方式
左单旋
代码
右单旋
代码
左右双旋
代码
右左双旋
代码
总体分析
创建结点
插入新结点
调整AVL树
完整代码
测试代码
AVL树本质是二叉搜索树(http://t.csdnimg.cn/XS5xi)
插入新结点之后,保证每个结点的左右子树高度之差的绝对值不超过1
平衡因子:右树-左树的高度(1,0,-1)可以通过平衡因子的方式来维护AVL树
子树的高度变化会继续向上影响祖先
子树的高度不变不会继续向上影响祖先
如果新增结点在左子树,父节点的bf-- bf:平衡因子
如果新增结点在右子树,父节点的bf++
三种情况:
1.父亲bf更新后==0,不用继续更新
2.父亲bf更新后==1或者-1,高度变化,需要继续向上更新
3.父亲bf更新后==2或者-2,需要进行调整
新结点插入较高右子树的右侧
插入后结点的bf变为1,父节点的bf变为2
然后进行左单旋
第一步:先将1的右指针指向2的左子树b(这里需要注意2的左子树可能为空),将b的父指针指向1
第二步:将2的左指针指向1,然后修改1和2的父指针(注意如果1可能也是子树,所以需要保存1的父节点,这里可以用root==1这个结点来进行判断
第三步:更新平衡因子,更新之后1和2的平衡因子都变为0
新结点插入较高左子树的左侧
插入后结点的bf变为-1,父节点的bf变为-2
然后进行右单旋
第一步:先将1的左指针指向2的右子树b(这里需要注意2的右子树可能为空),将b的父指针指向1
第二步:将2的右指针指向1,然后修改1和2的父指针(注意如果1可能也是子树,所以需要保存1的父节点,这里可以用root==1这个结点来进行判断
第三步:更新平衡因子,更新之后1和2的平衡因子都变为0
这里我们分情况进行讨论
1.h==0
结点3就是新增
2.h==1
新节点有两种情况新增
3.h>1
新节点有两种情况新增
综合以上三种情况可以看出这种新增方式会是2的bf变为1,1的bf变为-2
这些情况我们需要进行左右双旋
这里平衡因子更新也分三种情况
1. 3的bf==0
2. 3的bf==-1
3. 3的bf==1
分析同左右双旋
1.3的bf==0
2.3的bf==-1
3.3的bf==1
类比于二叉搜索树
#pragma once
#include
template
struct AVLTreeNode
{
AVLTreeNode* _left;
AVLTreeNode* _right;
AVLTreeNode* _parent;
pair _kv;
int _bf; //平衡因子
AVLTreeNode(const pair& kv)
: _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _kv(kv)
, _bf(0)
{ }
};
template
class AVLTree
{
typedef AVLTreeNode Node;
public:
bool Insert(const pair& kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
return true;
}
//找插入位置
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else
{
return false;
}
}
//插入新节点
cur = new Node(kv);
if (parent->_kv.first > kv.first)
{
parent->_left = cur;
cur->_parent = parent;
}
else
{
parent->_right = cur;
cur->_parent = parent;
}
//调整AVL树
while (parent)
{
if (cur == parent->_left)
{
parent->_bf--;
}
else
{
parent->_bf++;
}
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)
{
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)
{
RotateRL(parent);
}
else if (parent->_bf == -2 && cur->_bf == 1)
{
RotateLR(parent);
}
break;
}
else
{
assert(false);
}
}
return true;
}
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
subR->_left = parent;
Node* parentparent = parent->_parent; //先保存parent的父节点
parent->_parent = subR;
if (subRL) //判断左子树是否存在
subRL->_parent = parent;
if (_root == parent) //判断parent是否为根节点
{
_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 RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
subL->_right = parent;
Node* parentparent = parent->_parent; //先保存parent的父节点
parent->_parent = subL;
if (subLR) //判断右子树是否存在
subLR->_parent = parent;
if (_root == parent) //判断parent是否为根节点
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (parentparent->_left == parent)
{
parentparent->_left = subL;
}
else
{
parentparent->_right = subL;
}
subL->_parent = parentparent;
}
parent->_bf = subL->_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 == 0)
{
subL->_bf = subLR->_bf = parent->_bf = 0;
}
else if (bf == -1)
{
subLR->_bf = subL->_bf = 0;
parent->_bf = 1;
}
else if (bf == 1)
{
subLR->_bf = parent->_bf = 0;
subL->_bf = -1;
}
else
{
assert(false);
}
}
void RotateRL(Node* parent) //右左双旋
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf;
RotateR(parent->_right); //右单旋
RotateL(parent); //左单旋
if (bf == 0)
{
parent->_bf = subR->_bf = subRL->_bf = 0;
}
else if (bf == -1)
{
subRL->_bf = parent->_bf = 0;
subR->_bf = 1;
}
else if (bf == 1)
{
subRL->_bf = subR->_bf = 0;
parent->_bf = -1;
}
else
{
assert(false);
}
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
void PastOrder()
{
_PastOrder(_root);
cout << endl;
}
void PrvOrder()
{
_PrvOrder(_root);
cout << endl;
}
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_kv.first << ' ';
_InOrder(root->_right);
}
void _PrvOrder(Node* root)
{
if (root == nullptr)
{
return;
}
cout << root->_kv.first <<' ';
_PrvOrder(root->_left);
_PrvOrder(root->_right);
}
void _PastOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_PastOrder(root->_left);
_PastOrder(root->_right);
cout << root->_kv.first << ' ';
}
bool IsBalance()
{
return _IsBalance(_root);
}
int _Height(Node* root)
{
if (root == nullptr)
{
return 0;
}
int leftheight = _Height(root->_left);
int rightheight = _Height(root->_right);
return leftheight > rightheight ? leftheight + 1 : rightheight + 1;
}
bool _IsBalance(Node* root)
{
if (root == nullptr)
{
return true;
}
int leftheight = _Height(root->_left);
int rightHeight = _Height(root->_right);
if (root->_bf != rightHeight - leftheight)
{
cout << root->_kv.first << "平衡因子异常" << root->_bf << ' ' << rightHeight - leftheight << endl;
return false;
}
return abs(rightHeight - leftheight) < 2
&& _IsBalance(root->_left)
&& _IsBalance(root->_right);
}
private:
Node* _root = nullptr;
};
//void RotateR(Node* parent)
//{
// Node* SubL = parent->_left;
// Node* SubLR = Sub->_right;
//
// Node* parentparent = parent->_parent;
//
// parent->_left = SubLR;
// SubL->_right = parent;
//
// if(SubLR)
// SubLR->_parent = parent;
// parent->_parent = SubL;
// if (_root == parent)
// {
// _root = SubL;
// SubL->_parent = nullptr;
// }
// else
// {
// if (parentparent->_left == parent)
// {
// parentparent->_left = SubL;
// }
// else
// {
// parentparent->_right = SubL;
// }
// SubL->_parent = parentparent;
// }
// parent->_bf = SubL->_bf = 0;
//}