为什么会有AVL树?
极端情况下的二叉搜索树效率是O(n),如果调整二叉树搜索树的高度,那么树的搜索效率会达到O(log n).
( 这里简单介绍一下二叉搜索树:
当前结点大于它的左子树结点,小于右子树的结点,中序遍历是按照升序进行排列的。并且树中没有相同的结点: 二叉搜索树的实现.)
AVL树即平衡树,在二叉搜索树的前提下增加了平衡因子,使得每个结点的左右高度差不超过1.
平衡因子=右子树的高度-左子树的高度
AVL树的插入:
AVL的插入和二叉搜索树一样的方法,只不过需要更新平衡因子。
-
1.如果在左边插入,它的父亲结点的平衡因子–,右边则++
-
2.沿着这条路径一直向上更新,别的路径上的高度没有发生变化,所以不会影响其他无关路径的平衡因子
-
3.如果更新时发现平衡因子为0,则停止更新,因为插入结点后,并没有影响这个树的最大高度。如图
-
4 .如果平衡因子等于2或者-2,需要对其进行调整,具体调整方法如下
AVL树的调整:
1.向左旋转
2.向右旋转
3.先向左旋转,再向右旋转
添加的位置不同(b或者c),导致最后的平衡因子也不同
3.1如果bc的高度为0,那么经过旋转之后这三个的平衡因子都为0
3.2 在c处插入
3.3在b处插入
4.先向右旋转,再向左旋转
如果60结点的平衡因子为0,那么旋转之后30,60,90的平衡因子都为0
在c处插入
在b处插入
AVL树的简单实现
//插入以及旋转,平衡因子的调节,判断树是否平衡
#include <iostream>
using namespace std;
template<class K,class V>
struct AVL_Node
{
//左节点
AVL_Node<K,V> *left_node;
//右节点
AVL_Node<K,V>*right_node;
//父亲结点
AVL_Node<K,V>*parent_node;
//平衡因子
int bs;
//结点的值
pair<K,V> _kv;
AVL_Node(const pair<K,V> kv)
{
_kv=kv;
left_node=nullptr;
right_node=nullptr;
parent_node=nullptr;
bs=0;
}
};
template<class K,class V>
class AVL_Tree
{
typedef AVL_Node<K,V> Node;
public:
AVL_Tree()
{
_root=nullptr;
}
bool insert(pair<K,V> &kv)
{
Node * node=new Node(kv);
if(_root==nullptr)
{
_root=node;
return true;
}
Node *cur=_root;
Node * parent=nullptr;
while(cur)
{
if(cur->_kv.first>kv.first)
{
parent=cur;
cur=cur->left_node;
}
else if(cur->_kv.first<kv.first)
{
parent=cur;
cur=cur->right_node;
}
else
{
return false;
}
}
if(kv.first>parent->_kv.first)
{
parent->right_node=node;
node->parent_node=parent;
}
else
{
parent->left_node=node;
node->parent_node=parent;
}
//更新平衡因子
cur=node;
while(parent)
{
if(parent->left_node==cur)
{
--parent->bs;
}
if(cur==parent->right_node)
++parent->bs;
//不用再更新平衡因子
if(parent->bs==0)
{
//说明高度没变,将矮的那一端补上了
break;
}
else if(abs(parent->bs)==1)
{
cur=parent;
parent=parent->parent_node;
}
else if(abs(parent->bs)==2)
{
//说明已经不平衡了需要调整
//这里分为左单旋,右单旋,左右单旋和右左单旋
if(parent->bs==2)
{
if(cur->bs==1)
{
//左单旋
Rotate_L(parent);
}
else if(cur->bs==-1)
{
Node*sub=parent->right_node;
Node *subL=sub->left_node;
int subL_bs=subL->bs;
//先向右旋转
Rotate_R(sub);
//再向左旋转
Rotate_L(parent);
//调节平衡因子
if(subL_bs==1)
{
subL->bs=0;
sub->bs=0;
parent->bs=-1;
}
else if(subL_bs==-1)
{
parent->bs=0;
subL->bs=0;
sub->bs=1;
}
else if(subL->bs==0)
{
parent->bs=0;
sub->bs=0;
subL->bs=0;
}
}
}else
{
//parent->bs=-2;
if(parent->left_node->bs==-1)
{
//右旋转
Rotate_R(parent);
}
else if(parent->left_node->bs==1)
{
Node* sub=parent->left_node;
Node*subR=sub->right_node;
int subR_bs=subR->bs;
//先向左旋转
Rotate_L(sub);
//再向右旋转
Rotate_R(parent);
//调节平衡因子
if(subR_bs==-1)
{
sub->bs=0;
subR->bs=0;
parent->bs=1;
}
else if(subR_bs==1)
{
subR->bs=0;
parent->bs=0;
sub->bs=-1;
}
else if(subR->bs==0)
{
parent->bs=0;
sub->bs=0;
subL->bs=0;
}
}
}
break;
}
}
return true;
}
//左旋转
void Rotate_L(Node * parent)
{
Node* sub=parent->right_node;//parent的子节点
Node* subL=sub->left_node;//parent的子节点的左节点
Node *p_parent=parent->parent_node;//parent的父节点
if(parent==_root)
{
_root=sub;
sub->parent_node=nullptr;
}
else if(parent==p_parent->left_node)
{
p_parent->left_node=sub;
sub->parent_node=p_parent;
}
else
{
p_parent->right_node=sub;
sub->parent_node=p_parent;
}
parent->right_node=subL;
if(subL)
subL->parent_node=parent;
parent->parent_node=sub;
sub->left_node=parent;
sub->bs=parent->bs=0;
}
//右旋转
void Rotate_R(Node *parent)
{
Node *sub=parent->left_node;
Node *subR=sub->right_node;
Node *p_parent=parent->parent_node;
if(parent==_root)
{
_root=sub;
sub->parent_node=nullptr;
}
else if(parent==p_parent->left_node)
{
p_parent->left_node=sub;
}else
{
p_parent->right_node=sub;
}
sub->parent_node=p_parent;
parent->left_node=subR;
if(subR)
subR->parent_node=parent;
sub->right_node=parent;
parent->parent_node=sub;
sub->bs=parent->bs=0;
}
int height(Node *root)
{
if(root==nullptr)
return 0;
return max(height(root->left_node),height(root->right_node))+1;
}
void zhongxu(Node* root)
{
if(root==nullptr)
return ;
zhongxu(root->left_node);
cout<<root->_kv.first<<" ";
zhongxu(root->right_node);
}
bool is_balance(Node * root)
{
if(root==nullptr)
return true;
int right_h=height(root->right_node);
int left_h=height(root->left_node);
if(abs(right_h-left_h)==2)
{
cout<<"不平衡"<<endl;
return false;
}
if(root->bs!=(right_h-left_h))
{
return false;
}
return is_balance(root->left_node)&&is_balance(root->right_node);
}
void printf()
{
zhongxu(_root);
}
Node * get()
{
return _root;
}
private:
Node * _root;
};
void test()
{
AVL_Tree<int,int> avl;
avl.insert(pair<int,int>(90,0));
avl.insert(pair<int,int>(30,0));
avl.insert(pair<int,int>(100,0));
avl.insert(pair<int,int>(60,0));
avl.insert(pair<int,int>(50,0));
avl.printf();
avl.is_balance(avl.get());
}