平衡二叉树
如果二叉搜索树的插入序列是有序的或者是接近有序,那么二叉搜索树就会退化为单支数(类似单链表),查找元素相当于在顺序表中搜索元素,效率低下。
AVLtree(Adelson Velskii Landis tree)是一个加上额外平衡条件的二叉搜索树,左右子树高度之差(简称平衡因子)的绝对值不超过1,如果它有n个节点,高度可保持在O(logn),搜索时间复杂度为O(logn)。
AVL树的节点
template<class K, class V>
struct AVLTreeNode
{
AVLTreeNode<K, V>* _left;//左子节点
AVLTreeNode<K, V>* _right;//右子节点
AVLTreeNode<K, V>* _parent;//
int _bf; // 平衡因子,不是必须,我们这里选择用它来实现
pair<K, V> _kv;
AVLTreeNode(const pair<K, V>& kv)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _bf(0)
, _kv(kv)
{}
};
插入
- 先按照二叉搜索树的规则将节点插入到AVL树中
- 节点插入之后,对平衡因子进行更新
- 如果插入到左侧,只需要将平衡因子-1
- 如果插入到右侧,只需要将平衡因子+1
- 此时平衡因子有三种情况
- 平衡因子为0,插入之前平衡因子为正负1,插入后被调整为0,此时满足AVL树的性质,插入成功
- 平衡因子为正负1,插入之前平衡因子为0,插入之后需要继续向上更新
- 平衡因子为正负2,则违反了AVL树的性质,需要对其进行旋转处理
旋转处理
-
左单旋
void RotateL(Node* parent) { Node* subR=parent->_right; Node* subRL=subR->_left; parent->_right=subRL; //subRL则不用重新设置父节点 if(subRL) subRL->_parent=parent; subRL->_left=parent; Node* ppNode=parent->_parent; parent->_parent=subR; //判断parent是不是根节点 if(parent==_root) { _root=subR; subR->_parent=nullptr; } else { if(ppNode->_left==parent) ppNode->_left=subR; else ppNode->_right=sunR; subR->_parent=ppNode; } subR->bf=parent->_bf=0; }
-
右单选
void RotateR(Node* parent) { Node* subL=parent->_left; Node* subLR=subL->_right; parent->_left=subLR; if(subLR) subLR->_parent=parent; subL->_right=parent; Node* parent=parent->_parent; parent->_parent=subL; if(parent==_root) { _root=subL; subL->_parent=nullptr; } else { if(ppNode->_left==parent) ppNode->_left=subL; else ppNode->_right=subL; subL->_parent=ppNode; } parent->_bf=subL->_bf=0; }
-
左右双旋
void RetateLR(Node* parent) { Node* subL=parent->_left; Node* subLR=subL->_right; int bf=subLR->_bf; RotateL(parent->_left); RotateR(parent); if(bf==1) { parent->_bf=0; subL->_bf=1; subLR->_bf=0; } else if(bf==-1) { parent->_bf=-1; subR->_bf=0; subLR->_bf=0; } else if(bf==0) { parent->_bf=0; subR->_bf=0; subLR->_bf=0; } }
-
右左双旋
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=1; subR->_bf=0; subRL->_bf=0; } else if(bf==1) { parent->_bf=0; subR->_bf=-1; subRL->_bf=0; } else if(bf==0) { parent->_bf=0; subR->_bf=0; subRL->_bf=0; } }
插入的实现
bool Insert(const pair<K,V>& kv)
{
//1、按照二叉搜索树的规则进行插入
if(_root==nullptr)
{
_root=new Node(kv);
_root->_bf=0;
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;
cur->_parent=parent;
}
else
{
parent->_left=cur;
cur->_parent=parent;
}
//2、更新平衡因子
while(parent)
{
if(cur==parent->_right)
parent->_bf--;
else
parent->_bf++;
if(parent->_bf==0)
{
break;
}
else if(abs(parent->_bf)==1)
{
cur=parent;
parent=parent->_parent;
}
else if(abs(parent->_bf)==2)
{
//需要旋转来处理,来让二叉树平衡
if(parent->_bf==2)
{
if(cur->_bf==1)
RotateR(parent);
else if(cur->_bf==-1)
RotateLR(parent);
}
else if(parent->_bf==-2)
{
if(cur->_bf==-1)
RotateL(parent);
else if(cur->_bf==1)
RotateRL(parent);
}
break;
}
else
{
assert(false);
}
}
return true;
}
模拟实现
#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<const K, V> Node;
public:
AVLTree() = default;
// t2(t1)
AVLTree(const AVLTree<K, V>& t)
:_root(nullptr)
{
_root = _Copy(t._root);
}
Node* _Copy(Node* root)
{
if (root == nullptr)
return nullptr;
Node* newroot = new Node(root->_kv);
newroot->_bf = root->_bf;
newroot->_left = _Copy(root->_left);
newroot->_right = _Copy(root->_right);
return root;
}
~AVLTree()
{
_Destory(_root);
_root = nullptr;
}
void _Destory(Node* root)
{
if (root == nullptr)
return;
_Destory(root->_left);
_Destory(root->_right);
delete root;
}
bool Insert(const pair<K, V>& kv)
{
// 1.按搜索的规则将插入值
if (_root == nullptr)
{
_root = new Node(kv);
_root->_bf = 0;
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;
cur->_parent = parent;
}
else
{
parent->_left = cur;
cur->_parent = parent;
}
// 1.更新平衡因子
while (parent)
{
if (cur == parent->_right)
parent->_bf--;
else if (cur == parent->_left)
parent->_bf++;
if (parent->_bf == 0)
{
break;
}
else if (abs(parent->_bf) == 1)
{
cur = parent;
parent = parent->_parent;
}
else if (abs(parent->_bf) == 2)
{
// 说明parent子树已经不平衡,需要旋转处理,让他平衡
if (parent->_bf == 2)
{
if (cur->_bf == 1)
{
RotateR(parent);
}
else if (cur->_bf == -1)
{
RotateLR(parent);
}
}
else if (parent->_bf == -2)
{
if (cur->_bf == -1)
{
RotateL(parent);
}
else if (cur->_bf == 1)
{
RotateRL(parent);
}
}
break;
}
else
{
assert(false);
}
}
return true;
}
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
subR->_left = parent;
Node* ppNode = parent->_parent;
parent->_parent = subR;
if (parent == _root) {
_root = subR;
subR->_parent = nullptr;
}
else {
if (ppNode->_left == parent)
ppNode->_left = subR;
else
ppNode->_right = subR;
subR->_parent = ppNode;
}
subR->_bf = parent->_bf = 0;
}
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
subL->_right = parent;
Node* ppNode = parent->_parent;
parent->_parent = subL;
if (parent == _root)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
ppNode->_left = subL;
else
ppNode->_right = subL;
subL->_parent = ppNode;
}
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 == 1)
{
parent->_bf = 0;
subL->_bf = 1;
subLR->_bf = 0;
}
else if (bf == -1)
{
parent->_bf = -1;
subL->_bf = 0;
subLR->_bf = 0;
}
else if (bf == 0)
{
parent->_bf = 0;
subL->_bf = 0;
subLR->_bf = 0;
}
}
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 = 1;
subR->_bf = 0;
subRL->_bf = 0;
}
else if (bf == 1)
{
parent->_bf = 0;
subR->_bf = -1;
subRL->_bf = 0;
}
else if (bf == 0)
{
parent->_bf = 0;
subR->_bf = 0;
subRL->_bf = 0;
}
}
void _InOrder(Node* root)
{
if (root == nullptr)
return;
_InOrder(root->_left);
cout << root->_kv.first << " ";
_InOrder(root->_right);
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
int _Depth(Node* root)
{
if (root == nullptr)
return 0;
int leftDepth = _Depth(root->_left);
int rightDepth = _Depth(root->_right);
return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}
bool _IsBalance(Node* root)
{
if (root == nullptr)
return true;
int leftDepth = _Depth(root->_left);
int rightDepth = _Depth(root->_right);
if (leftDepth - rightDepth != root->_bf)
{
cout << root->_kv.first << ":平衡因子异常" << endl;
//return false;
}
return abs(leftDepth - rightDepth) < 2
&& _IsBalance(root->_left)
&& _IsBalance(root->_right);
}
bool IsBalance()
{
return _IsBalance(_root);
}
Node* Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (cur->_kv.first < key)
cur = cur->_right;
else if (cur->_kv.first > key)
cur = cur->_left;
else
return cur;
}
return NULL;
}
private:
Node* _root = nullptr;
};