您的位置:首页 > 其它

高度平衡的二叉搜索树-----AVL树

2016-09-22 15:18 337 查看
AVL树是高度平衡的二叉搜索树,它能保持二叉树的高度平衡,尽可能降低二叉树的高度,减少数的平均搜索长度

AVL树的几个特点:

1.左右子树高度绝对值不超过1

2.树的每左右子树都是AVL树

3.每个节点的平衡因子是-1,0,1(平衡因子 = 右子树高度-左子树高度)

一棵AVL树有N个节点,其高度可以保持在log2N,插入/删除/查找的复杂度也在log2N(log2N就是以2为底N的对数)

AVL树通过不停的旋转达到它的特性

左单旋:



void _RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;

//把subRL给父节点(parent),做其右节点
parent->_right = subRL;
if(subRL)//若subRL不为空,把它的父亲节点置为父节点(parent)
subRL->_parent = parent;
subR->_left = parent;
Node* ppNode = parent->_parent;//
parent->_parent = subR;//让subR成为中间那个节点(即父节点的父亲节点)

if(ppNode == NULL)//父节点是根节点
{
_root = subR;
_root->_parent = NULL;
}
else
{
//parent是ppNode的左孩子,则subR也成为ppNode的左孩子,parent是ppNode的右孩子,则subR也是ppNode的右孩子
if(ppNode->_left == parent)
{
ppNode->_left = subR;
}
else
ppNode->_right = subR;
subR->_parent = ppNode;
}
//完成旋转后,平衡因子变为0
subR->_bf = parent->_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(ppNode == NULL)
{
_root = subL;
subL->_parent = NULL;
}
else
{
if(ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
ppNode->_right = subL;
subL->_parent = ppNode;
}
subL->_bf = parent->_bf = 0;
}
左右双旋:



特殊情况会涉及到平衡因子的调节





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

_RotateL(subL);
_RotateR(parent);

if(bf == 1)
{
//subL只有一个左孩子,无右孩子,平衡因子为-1
subL->_bf = -1;
//subLR的右孩子成为了parent的左孩子,与原有的右孩子平衡,平衡因子为0
parent->_bf = 0;
}
else if(bf == -1)
{
//subLR的左孩子成为subR的右孩子,平衡因为为0
subL->_bf = 0;
//parent只有一个右孩子,平衡因子为1
parent->_bf = 1;
}
else
{
//subLR既有左孩子又有右孩子,subLR的左孩子成为subL的右孩子,sunLR的右孩子成为parent的左孩子,平衡因子都为0
subLR->_bf = subL->_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 == 1)//subRL的平衡因子为1时
{
//subRL只有一个右孩子,完成旋转后,subRL的右孩子成为subR的左孩子,subR本来有一个右孩子,左右孩子数相等平衡因子为0
subR->_bf = 0;
//parent节点右孩子为subR,完成旋转后,是将subRL的左孩子赋给他做他的右孩子,可是subRL平衡因子为1,无左孩子,则parent完成旋转后无右孩子,平衡因子为-1
parent->_bf = -1;
}
else if(bf == -1)
{
//subR只有一个右孩子,左孩子subRL成为父亲节点后无左孩子,平衡因子为1
subR->_bf = 1;
//subRL的左孩子成为parent的右孩子,与parent本来有的左孩子平衡,平衡因子为0
parent->_bf = 0;
}
else
{
//最后一种情况subRL既有左孩子又有右孩子,subRL的左孩子成为parent的右孩子,subRL的右孩子成为subR的左孩子,平衡因子都为0
subRL->_bf = subR->_bf = parent->_bf = 0;
}
}

代码实现:
AVLTree.h#pragma once

#include <iostream>
using namespace std;
template<class K,class V>
struct AVLTreeNode
{
K _key;
V _value;
int _bf;
AVLTreeNode<K,V>* _left;
AVLTreeNode<K,V>* _right;
AVLTreeNode<K,V>* _parent;

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

template<class K,class V>
struct 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;
}

//寻找key值插入的位置
Node* parent = NULL;
Node* cur = _root;
while(cur)
{
if(cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if(cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else
return false;
}
//把cur连接到树上
cur = new Node(key,value);
if(parent->_key > key)
{
parent->_left = cur;
cur->_parent = parent;
}
else
{
parent->_right = cur;
cur->_parent = parent;
}

//更新平衡因子
while(parent)
{
if(cur == parent->_left)
{
parent->_bf--;
}
else
parent->_bf++;

//旋转调节树和平衡因子
if(parent->_bf == -1||parent->_bf == 1)
{
//往上查询父节点的平衡因子
cur = parent;
parent = cur->_parent;

}
else if(parent->_bf == 0)
break;
else //parent->_bf == 2||parent->_bf == -2
{
if(parent->_bf == 2)
{
if(cur->_bf == 1)
_RotateL(parent);//左单旋
else //cur->_bf == -1
_RotateRL(parent);//右左双旋
}
if(parent->_bf == -2) //parent->_bf == -2
{
if(cur->_bf == -1)
_RotateR(parent);//右单旋
else //cur->_bf == 1
_RotateLR(parent);//左右双旋
}

break;
}
}

}
void _RotateL(Node* parent);

void _RotateR(Node* parent);

void _RotateRL(Node* parent);

void _RotateLR(Node* parent);

bool IsBlance()
{
return _IsBlance(_root);
}
bool _IsBlance(Node* root)
{
//如果为空树,直接返回true
if(root == NULL)
return true;
int left = Height(root->_left);
int right = Height(root->_right);

if(root->_bf != (right-left))//root的平衡因子等于右子树高度-左子树高度
{
cout<<root->_key<<endl;
return false;
}

return abs(right-left)<2 //平衡因子为-1,0,1,绝对值小于2
&&_IsBlance(root->_left)
&&_IsBlance(root->_right);
}

int Height(Node* root)
{
if(root == NULL)
return 0;
int left = Height(root->_left);
int right = Height(root->_right);

return left>right ? left+1 : right+1;
}
void InOrderSort()
{
_InOrderSort(_root);
cout<<endl;
}

void _InOrderSort(Node* root)
{
if(root == NULL)
return;

_InOrderSort(root->_left);
cout<<root->_value<<" ";
_InOrderSort(root->_right);
}
private:
Node* _root;
};Test.cp
void Test()
{
int arr[] = {4,2,6,1,3,5,15,7,16,14};
int size = sizeof(arr)/sizeof(arr[0]);

AVLTree<int,int> a;
int i = 0;
for (;i < size;i++)
{
a.Insert(arr[i],i);
}

cout<<a.IsBlance()<<endl;
a.InOrderSort();
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: