1 Star 0 Fork 0

晚风不及你的笑 / 作业库

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
AVLTree.h 6.17 KB
一键复制 编辑 原始数据 按行查看 历史
晚风不及你的笑 提交于 2023-02-13 21:48 . AVL树代码
#pragma once
template<class K,class V>
struct AVLTreeNode
{
AVLTreeNode(const pair<K, V>& kv)
:_kv(kv)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _bf(0)//平衡因子默认是0
{}
pair<K, V> _kv;
AVLTreeNode<K, V>* _left;//左孩子
AVLTreeNode<K, V>* _right;//右孩子
AVLTreeNode<K, V>* _parent;//父节点
int _bf;//平衡因子
};
template<class K,class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
//插入,插入的操作还是跟二叉搜索树的插入基本一致,
//需要注意的是平衡因子的更新,和更新后的旋转
bool Insert(const pair<K, V>& kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
return true;
}
Node* cur = _root;
Node* parent = nullptr;
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;
}
//更新平衡因子
while (parent)
{
//插入在左,parent的平衡因子--
//插入在右,parent的平衡因子++
if (parent->_left == cur)
{
parent->_bf--;
}
else
{
parent->_bf++;
}
//是否继续更新,要看子树高度的变化
//1.parent的平衡因子是0,说明插入之前,Parent的平衡因子为正负1,
// 插入后被调整成0,此时满足AVL树的性质,插入成功
//2.,parent的平衡因子是-1或1,说明插入之前,parent的平衡因子是0,
// 插入后被调整为正负1,此时子树高度发生变化,需要继续向上更新平衡因子
//3.parent的平衡因子是正负2,说明插入之前,Parent的平衡因子为正负1,
// 说明插入之后严重影响平衡,需要就地处理:旋转
//
// 旋转之后:
// 1、让这颗子树左右高度不超过1
// 2、旋转过程中继续保持他是搜索树
// 3、更新调整孩子节点的平衡因子
// 4、让这颗子树的高度跟插入前保持一致
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)
{
RotateLR(parent);
}
//右左双旋
else if (parent->_bf == 2 && cur->_bf == -1)
{
RotateRL(parent);
}
else
{
assert(false);
}
break;
}
else
{
assert(false);
}
}
return true;
}
//左右双旋:先向左单旋,再向右单旋
void RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLr = subL->_right;
int bf = subLr->_bf;
RotateL(parent->_left);
RotateR(parent);
if (bf == -1)//subLr左子树新增
{
parent->_bf = 1;
subL->_bf = 0;
subLr->_bf = 0;
}
else if (bf == 1)//subLr右子树新增
{
parent->_bf = 0;
subL->_bf = -1;
subLr->_bf = 0;
}
else if (bf == 0)//subLr自己就是新增
{
parent->_bf = 0;
subL->_bf = 0;
subLr->_bf = 0;
}
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 == -1)
{
parent->_bf = 0;
subR->_bf = 1;
subRl->_bf = 0;
}
else if (bf == 1)
{
parent->_bf = -1;
subR->_bf = 0;
subRl->_bf = 0;
}
else if(bf == 0)
{
parent->_bf = 0;
subR->_bf = 0;
subRl->_bf = 0;
}
else
{
assert(false);
}
}
//向左单旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRl = subR->_left;
parent->_right = subRl;
//subRl不为空就让父指针指向parent节点
if (subRl)
subRl->_parent = parent;
//让
Node* pNode = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (pNode == nullptr)
{
_root = subR;
_root->_parent = nullptr;
}
else
{
if (pNode->_left == parent)
{
pNode->_left = subR;
}
else
{
pNode->_right = subR;
}
subR->_parent = pNode;
}
//更新旋转后的平衡因子
parent->_bf = subR->_bf = 0;
}
//向右单旋
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLr = subL->_right;
parent->_left = subLr;
if (subLr)
subLr->_parent = parent;
Node* pNode = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
if (pNode == nullptr)
{
_root = subL;
_root->_parent = nullptr;
}
else
{
if (pNode->_left == parent)
{
pNode->_left = subL;
}
else
{
pNode->_right = subL;
}
subL->_parent = pNode;
}
parent->_bf = subL->_bf = 0;
}
//中序遍历
void InOrder()
{
_InOrder(_root);
cout << endl;
}
void _InOrder(Node* root)
{
if (root == nullptr)
return;
_InOrder(root->_left);
cout << root->_kv.first << ":" << root->_kv.second << endl;;
_InOrder(root->_right);
}
//高度
int Height(Node* root)
{
if (root == nullptr)
return 0;
int lh = Height(root->_left);
int rh = Height(root->_right);
return lh > rh ? lh + 1 : rh + 1;
}
//判断AVL树是否正常
bool IsBalance()
{
return _IsBalance(_root);
}
bool _IsBalance(Node* root)
{
//空树也是AVL树
if (root == nullptr)
{
return true;
}
int leftHeight = Height(root->_left);
int rightHeight = Height(root->_right);
//这里可以很方便的帮助我们看到哪个节点的平衡因子异常了
if (rightHeight - leftHeight != root->_bf)
{
cout<< root->_kv.first <<"平衡因子异常" << endl;
}
//这里求的是绝对值,所以算出来的值只要小于2,
//根和每个子树同样满足条件,才认为这个AVL树是正常的
return abs(leftHeight - rightHeight) < 2
&& _IsBalance(root->_left)
&& _IsBalance(root->_right);
}
private:
Node* _root = nullptr;
};
void test1()
{
//int arr[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
int arr[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
AVLTree<int, int> at;
for (auto& e : arr)
{
at.Insert(make_pair(e, e));
}
at.InOrder();
cout << at.IsBalance() << endl;
}
void test2()
{
#define N 10000
srand(time(NULL));
AVLTree<int, int> at;
for (size_t i = 0;i< N;++i)
{
size_t e = rand();
at.Insert(make_pair(e, e));
}
//at.InOrder();
cout << at.IsBalance() << endl;
}
1
https://gitee.com/sendy-jing/job-library.git
git@gitee.com:sendy-jing/job-library.git
sendy-jing
job-library
作业库
master

搜索帮助