一、模拟实现AVL树
AVL树就是高度平衡二叉搜索树
所有树的左右子树高度差不超过1
平衡因子 = 右子树高度 - 左子树高度
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
template<class K,class V>
struct AVLTreeNode
{
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent; //三叉链
int _bf; //平衡因子 balance factor
pair<K, V> _kv;
AVLTreeNode(const pair<K, V>& kv)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_bf(0)
,_kv(kv)
{}
};
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!=nullptr)
{
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 (cur->_kv.first > parent->_kv.first)
{
parent->_right = cur;
cur->_parent = parent;
}
else
{
parent->_left = cur;
cur->_parent = parent;
}
//1.cur是parent的左,parent->_bf--,是右则++;
//2.更新后的_bf如果是0,说明parent高度没有发生变化 : 更新前_bf为 -1/1 ,变为0说明把矮的那边填上
//3.更新后的_bf为-1/1,说明parent变高了,继续向上更新
//4.更新后的_bf为-2/2,说明parent的子树出现了不平衡,需要进行旋转处理
//开始更新平衡因子
while (parent)
{
if (cur == parent->_right)
parent->_bf++;
else
parent->_bf--;
if (parent->_bf == 0)
break; //parent所在的子树高度没有变化,更新结束
else if (parent->_bf == 1 || parent->_bf == -1)
{
//parent所在的子树变高了,需要继续向上进行更新
cur = parent;
parent = parent->_parent;
}
else if (parent->_bf == 2 || parent->_bf == -2)
{
//parent所在的子树出现了不平衡,需要旋转更新
//右重,向左压,左单旋
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);
else
assert(false);
break;
}
else
assert(false);
}
}
void RotateL(Node*& parent) //左旋,\ 右重
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
Node* ppNode = parent->_parent;
subR->_left = parent;
parent->_right = subRL;
parent->_parent = subR;
if (subRL != nullptr) //当其为空时不用赋值,且赋值时会访问错误 : nullptr->_parent
{
subRL->_parent = parent;
}
if (ppNode == nullptr) //parent就是根
{
_root = subR;
subR->_parent = nullptr;
}
else //parent是子树
{
if (ppNode->_left == parent)
ppNode->_left = subR;
else
ppNode->_right = subR;
subR->_parent = ppNode;
}
parent->_bf = 0;
subR->_bf = 0;
}
void RotateR(Node*& parent) //右旋,/ 左重
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
Node* ppNode = parent->_parent;
if (ppNode == nullptr)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
ppNode->_left = subL;
else
ppNode->_right = subL;
subL->_parent = ppNode;
}
if (subLR != nullptr)
{
subLR->_parent = parent;
}
parent->_left = subLR;
parent->_parent = subL;
subL->_right = parent;
parent->_bf = 0;
subL->_bf = 0;
}
void RotateRL(Node*& parent) //先右单旋再左单旋 \
// /\;
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
int tmp_bf = 0;
if (subRL->_left == nullptr && subRL->_right == nullptr) //subRL无子树时,其他树也无子树,相当于只有三棵树
{
tmp_bf = 0;
}
else
{
tmp_bf = subRL->_bf; //通过判断tmp_bf大小来对旋转后的各树_bf进行不一样的赋值方式
}
RotateR(subR); //注意传入的参数
RotateL(parent);
if (tmp_bf == 0)
{
parent->_bf = 0;
subR->_bf = 0;
}
else if(tmp_bf == 1)
{
parent->_bf = -1;
subR->_bf = 0;
}
else if (tmp_bf == -1)
{
parent->_bf = 0;
subR->_bf = 1;
}
subRL->_bf = 0;
}
void RotateLR(Node*& parent)//先左单旋再右单旋 /
// /\;
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
int tmp_bf = 0;
if (subLR->_left == nullptr && subLR->_right == nullptr)
tmp_bf = 0;
else
tmp_bf = subLR->_bf;
RotateL(subL);
RotateR(parent);
if (tmp_bf == 0)
{
subL->_bf = 0;
parent->_bf = 0;
}
else if (tmp_bf == 1)
{
subL->_bf = -1;
parent->_bf = 0;
}
else if(tmp_bf == -1)
{
subL->_bf = 0;
parent->_bf = 1;
}
subLR->_bf = 0;
}
void Print()
{
_Print(_root);
}
void _Print(Node*& cur)
{
if (cur == nullptr)
return;
_Print(cur->_left);
cout << cur->_kv.first << ":" << cur->_kv.second << endl;
_Print(cur->_right);
}
int Height(Node* root)
{
if (root == nullptr)
return 0;
int left = 1 + Height(root->_left);
int right = 1 + Height(root->_right);
return left > right ? left : right;
}
bool Check()
{
return _Check(_root);
}
bool _Check(Node* root)
{
if (root == nullptr)
return true;
int leftHeight = Height(root->_left);
int rightHeight = Height(root->_right);
int dif = rightHeight - leftHeight;
if (dif != root->_bf)
{
cout << "No" << endl;
return false;
}
if (abs(dif) > 1)
{
cout << "Not" << endl;
return false;
}
return _Check(root->_left) && _Check(root->_right);
}
private:
Node* _root = nullptr;
};