您的位置:首页 > 理论基础 > 数据结构算法

【平衡搜索树】AVL树

2016-11-10 12:02 399 查看
【前言】:之前学过了二叉搜索树,但是二叉搜索树有一个很大的缺陷,就是当当原本的数据有序或者接近有序的时候,这棵树的高度就为N(假设原本的数据个数为N),那么在搜索的时候它的时间复杂度(这里考虑最坏情况下的)就为O(N), 搜索的效率就比较低。那么,为了改进这个缺陷,我们就尽量让这棵搜索树变得比较平衡,降低它的高度,这样就可以提高它的搜索效率。

AVL树
一、定义:

AVL树又称为高度平衡的二叉搜索树,它能保持搜索二叉树的高度平衡,尽量降低树的高度,减少树的平均搜索长度,从而提高搜索的效率。

二、性质:

1. 左右子树高度差的绝对值 <= 1

2. AVL树的每个左子树和右子树仍是AVL树

3. 每个节点都有一个平衡因子(balancefactor--bf) = 右子树高度 - 左子树高度,任一结点的平衡因子是-1,0,1。

三、结点结构设计:

因为每个节点都需要判断以这个结点为根的这棵树是否平衡,所以我们要在搜索二叉树结点的基础上加上判断这棵树是否平衡的变量。

有两种思路:(1)加入当前树的高度  (2)加入平衡因子,我们选择第二种思路。

结点的结构定义如下:

<span style="font-size:18px;">template <class K, class V>
struct AVLTreeNode
{
K _key; //关键码
V _value;
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;
int _bf; //平衡因子
};</span>


四、实现思路:

对于搜索树,我们主要实现它的三个接口:插入(Insert),删除(Remove)和 查找(Find)。

查找和我们搜索二叉树的基本一样,主要是插入和删除,这两个思想一致,我们这里就分析一下实现插入的思路。

插入主要步骤:

1.首先,和搜索二叉树一样,先把新结点插入进去;

2.调整平衡因子:向左插入平衡因子-1,向右插入+1;

3.检查平衡因子,调整这棵树:(如下图解释)

    (1)当平衡因子为 1/-1, 继续向父节点调整,直到父节点为空;

    (2)当平衡因子为 0, 则不需要向父节点调整,跳出循环;

    (3)当平衡因子为 2/-2,则需要旋转,使该节点平衡因子变为0,然后跳出循环。

                  




 



五、搜索的时间复杂度:O(logN)

六、下面附上实现代码和测试用例

1.AVLTree.h

#pragma once
#include<iostream>
using namespace std;

template <class K, class V>
struct AVLTreeNode
{
K _key;
V _value;
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;
int _bf; //平衡因子

AVLTreeNode(const K& key, const V& value)
:_key(key)
,_value(value)
,_left(NULL)
,_right(NULL)
,_parent(NULL)
,_bf(0)
{}
};

template <class K, class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
AVLTree()
:_root(NULL)
{}

bool Insert(const K& key, const V& value)
{
if(_root == NULL)
{
_root = new Node(key, value);
return true;
}

//查找插入位置
Node* parent = NULL;
Node* cur = _root;
while(cur)
{
if(cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else if(cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else
return false;
}

//插入
cur = new Node(key, value);
if(parent->_key > key) //parent的左插入
{
parent->_left = cur;
cur->_parent = parent;

//调整平衡因子
--parent->_bf;
_AdjustTree(parent);
}
else	//parent的右插入
{
parent->_right = cur;
cur->_parent = parent;
++parent->_bf;
_AdjustTree(parent);
}
return true;
}

void InOrder()
{
_InOrder(_root);
cout << endl;
}

bool IsBalance()
{
return _IsBalance(_root);
}

~AVLTree()
{
_Release(_root);
}
protected:
void _Release(Node* root)
{
if(root == NULL)
return;
_Release(root->_left);
_Release(root->_right);

delete root;
root = NULL;
}
void _AdjustTree(Node* parent)
{
//检查平衡因子
while(parent)
{
if(parent->_bf == 0)//平衡因子为0,停止
break;
else if(parent->_bf == 1 ||parent->_bf == -1)//平衡因子为1/-1,继续向父结点调整
{
Node* sub = parent;
parent = parent->_parent;
if(parent)
{
if(parent->_left == sub)
--parent->_bf;
else
++parent->_bf;
}
}
else//平衡因子为2/-2,旋转
{
if(parent->_bf==2 && parent->_right->_bf==1)
{
//左旋
_RotateL(parent);
}
else if(parent->_bf==2 && parent->_right->_bf==-1)
{
//右左双旋
_RotateRL(parent);
}
else if(parent->_bf==-2 && parent->_left->_bf==-1)
{
//右旋
_RotateR(parent);
}
else //parent->_ba==-2 && parent->_left->_ba==1
{
//左右双旋
_RotateLR(parent);
}
break;
}
}
}
//右旋
void _RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;

//subLR 和 parent
parent->_left = subLR;
if(subLR) //注意:有可能为空
subLR->_parent = parent;

//subL 和 pp
Node* pp = parent->_parent;
subL->_parent = pp;
if(pp)
{
if(pp->_left == parent)
pp->_left = subL;
else
pp->_right = subL;
}
else
{
_root = subL;
subL->_parent = NULL;
}

//subL 和 parent
subL->_right = parent;
parent->_parent = subL;

//改平衡因子
subL->_bf = parent->_bf = 0;
}
void _RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;

//subRL 和 parent
parent->_right = subRL;
if(subRL) //注意:有可能为空
subRL->_parent = parent;

//pp 和 subR
Node* pp = parent->_parent;
subR->_parent = pp;
if(pp)
{
if(pp->_left == parent)
pp->_left = subR;
else
pp->_right = subR;
}
else
{
_root = subR;
subR->_parent = NULL;
}
//parent 和 subR
subR->_left = parent;
parent->_parent = subR;

//改平衡因子
subR->_bf = parent->_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 == 0)
{
parent->_bf = subR->_bf = subRL->_bf;
}
else if(bf == 1)
{
parent->_bf = -1;
subRL->_bf = 0;
subR->_bf = 0;
}
else
{
parent->_bf = 0;
subRL->_bf = 0;
subR->_bf = 1;
}
}

void _RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
int bf = subLR->_bf;
_RotateL(parent->_left);
_RotateR(parent);

if(bf == 0)
{
subLR->_bf = subL->_bf = parent->_bf = 0;
}
else if(bf == 1)
{
parent->_bf = 0;
subLR->_bf = 0;
subL->_bf = -1;
}
else
{
parent->_bf = 1;
subLR->_bf = 0;
subL->_bf = 0;
}
}

void _InOrder(Node* root)
{
if(root == NULL)
return;
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}

size_t _Height(Node* root)
{
if(root == NULL)
return 0;
size_t LHeight = _Height(root->_left);
size_t RHeight = _Height(root->_right);

return (LHeight>RHeight) ? (LHeight+1) : (RHeight+1);
}

bool _IsBalance(Node* root)
{
if(root == NULL)
return true;

int bf = _Height(root->_right)-_Height(root->_left);
if(bf != root->_bf)
cout << "平衡因子异常 key:"<<root->_key<< endl;

if(abs(bf) < 2)
return _IsBalance(root->_left) && _IsBalance(root->_right);
else
return false;
}
protected:
Node* _root;
};


2.Test.cpp

#include<iostream>
#include"AVLTree.h"
using namespace std;

//测试用例一
void TestAVLTree1()
{
int arr[] = {16, 3, 7, 11, 9, 26, 18, 14, 15};
AVLTree<int, int> t1;
for(int i = 0; i<sizeof(arr)/sizeof(arr[0]); ++i)
{
t1.Insert(arr[i], i);
}
t1.InOrder();
cout<<"IsBalance() ? "<<t1.IsBalance()<<endl;
}

//测试用例二
void TestAVLTree2()
{
int arr[] = {4, 2, 6, 1, 3, 5, 15, 7, 16, 14};
AVLTree<int, int> t2;
for(int i = 0; i<sizeof(arr)/sizeof(arr[0]); ++i)
{
t2.Insert(arr[i], i);
}
t2.InOrder();
cout<<"IsBalance() ? "<<t2.IsBalance()<<endl;
}

int main()
{
TestAVLTree1();
cout << endl;
TestAVLTree2();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息