2.旋转
2.3.1旋转的原则
1.保持搜索树的原则
2.让旋转的树从不平衡变平衡,会降低这棵树的高度
2.3.2右单旋

本质就是将a这颗子树上升一层来解决平衡因子过大的问题
cpp
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
if (subLR)
{
subLR->_parent = parent;
}
parent->_left = subLR;
subL->_right = parent;
Node* pParent = parent->_parent;
parent->_parent = subL;
if (parent == _root)
{
_root = subL;
_root->_parent = nullptr;
}
else
{
if (pParent->_left == parent)
{
pParent->_left = subL;
}
else
{
pParent->_right = subL;
}
subL->_parent = pParent;
}
subL->_bf = 0;
parent->_bf = 0;
}
2.3.3左单旋

原理同上,但是编写时要注意平衡因子的更新和parent节点的更新
cpp
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
{
subRL->_parent = parent;
}
Node* pParent = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (pParent == nullptr)
{
_root = subR;
subR->_parent = nullptr;
}
else
{
if (parent == pParent->_left)
{
pParent->_left = subR;
}
else
{
pParent->_right = subR;
}
subR->_parent = pParent;
}
parent->_bf = subR->_bf = 0;
}
2.3.4左右双旋


左右双旋就是不是纯粹的一边高,这个时候如果进行纯粹的单旋转就会出现下图的情况,注意不要看上标

此时最好的办法就是先在5这个左节点先进行单旋,让其变成纯粹的一边高,然后在进行正常的单旋
cpp
//左右双旋转
void RotateLR(Node* parent)
{
RotateL(parent->_left);
RotateR(parent);
}
旋转代码参考上面
注意:还有很多细节,比如平衡因子的更新之类的重点没有提到,不代表可以忽略!!!
注意:还有很多细节,比如平衡因子的更新之类的重点没有提到,不代表可以忽略!!!
注意:还有很多细节,比如平衡因子的更新之类的重点没有提到,不代表可以忽略!!!
详细的参考代码部分
cpp
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
template<class K,class V>
struct AVLTreeNode
{
pair<K, V> _kv;
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;
int _bf;
AVLTreeNode(const pair<K,V>& kv)
:_kv(kv),
_right(nullptr),
_left(nullptr),
_parent(nullptr),
_bf(0)
{ }
};
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* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(kv);
if (parent->_kv.first < kv.first)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;
//控制平衡
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)
{
RotateR(parent);
}
else if (parent->_bf == 2 && cur->_bf == 1)
{
RotateL(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 RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
if (subLR)
{
subLR->_parent = parent;
}
parent->_left = subLR;
subL->_right = parent;
Node* pParent = parent->_parent;
parent->_parent = subL;
if (parent == _root)
{
_root = subL;
_root->_parent = nullptr;
}
else
{
if (pParent->_left == parent)
{
pParent->_left = subL;
}
else
{
pParent->_right = subL;
}
subL->_parent = pParent;
}
subL->_bf = 0;
parent->_bf = 0;
}
//左旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
{
subRL->_parent = parent;
}
Node* pParent = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (pParent == nullptr)
{
_root = subR;
subR->_parent = nullptr;
}
else
{
if (parent == pParent->_left)
{
pParent->_left = subR;
}
else
{
pParent->_right = subR;
}
subR->_parent = pParent;
}
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)
{
subLR->_bf = 0;
subL->_bf = 0;
parent->_bf = 1;
}
else if (bf == 1)
{
subLR->_bf = 0;
subL->_bf = -1;
parent->_bf = 0;
}
else if(bf == 0)
{
subLR->_bf = 0;
subL->_bf = 0;
parent->_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 == 0)
{
subR->_bf = 0;
subRL->_bf = 0;
parent->_bf = 0;
}
else if (bf == 1)
{
subR->_bf = 0;
subRL->_bf = 0;
parent->_bf = -1;
}
else if (bf == -1)
{
subR->_bf = 1;
subRL->_bf = 0;
parent->_bf = 0;
}
else
{
assert(false);
}
}
//中序遍历
void InOrder()
{
_InOrder(_root);
cout << endl;
}
bool IsBalanceTree()
{
return _IsBalanceTree(_root);
}
int Size()
{
return _Size(_root);
}
private:
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 leftHeight = _Height(root->_left);
int rightHeight = _Height(root->_right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
//平衡检查
bool _IsBalanceTree(Node* root)
{
if (root == nullptr)
return true;
int leftHeight = _Height(root->_left);
int rightHeight = _Height(root->_right);
int diff = leftHeight - rightHeight;
//abs是绝对值的计算
if (abs(diff) >= 2)
{
cout << root->_kv.first << "高度异常" << endl;
return false;
}
if (root->_bf != diff)
{
cout << root->_kv.first << "数据异常" << endl;
return false;
}
return _IsBalanceTree(root->_left) && _IsBalanceTree(root->_right);
}
int _Size(Node* root)
{
if (root == nullptr)
{
return 0;
}
return _Size(root->_left) + _Size(root->_right) + 1;
}
private:
Node* _root = nullptr;
};