作者:一觉亮天 日期:2007-7-21
AVL树的定义
说AVL树要先说二叉搜索树。二叉搜索树(Binary
Search Tree)是这样的二叉树:二叉树的左子树如果不为空,则所有节点的值都小于父节点;二叉树的右子树如果不为空,则所有节点的值都大于父节点。
二叉搜索树中查找操作的平均时间复杂度是O(logn),以这种方式组织数据可以节约查找时间。但二叉搜索树如果构造不恰当的话,最坏情况下,查找操作的时间复杂度可能会是O(n)。比如下面图1这种情况:
图1
图1所示的树被认为是不平衡的,为此引入了平衡二叉搜索树(Balanced Binary Search Tree)的概念。平衡二叉搜索树就是给二叉搜索树增加一些平衡条件,使她不是太瘦高。AVL树就是平衡二叉树的一种。AVL是两个人名字的首字母缩写。在说AVL树平衡条件之前需要引入树的高度的概念。由图2就可以理解对树的高度的定义了。规定空树的高度是-1。
图2
AVL树规定树二叉搜索树的左子树的高度和右子树的高度之差的绝对值不能大于1。
AVL树的插入和删除操作
AVL树的插入操作和删除操作的第一步和普通二叉搜索树的插入和删除操作相同。
插入操作就是依照二叉搜索树的定义把插入的元素放在合适的位置。
删除操作可以以下面的算法完成:
找到要删除的节点,如果是叶子节点则直接删除;如果只包含左子树或右子树,则删除此节点,相应的左子树或右子树位置上移;如果既包含左子树又包含右子树,则可以找到此节点右子树中最小的节点,把值赋给待删除节点,然后在此节点的右子树删除最小的节点。
进行完普通二叉搜索树的插入操作和删除操作后,有可能破坏AVL树的平衡条件,这时就可以通过树的旋转操作来使她重新平衡。
树的旋转操作
往AVL树中插入元素,如果导致了树的不平衡,能通过下面的任意一种旋转操作使树重新平衡。
RR
如图3所示,节点5的左子树高度是1,右子树高度是-1,需要对树进行右旋操作。右旋操作的步骤是:节点5的左子树指向节点4的右子树,结点4的右子树指向节点5。
RL
如图4所示,节点4的左子树高度是1,右子树高度是-1,需要对树进行右旋操作。但是如果单纯做右旋操作的话,并不能使树平衡。这时需要两次旋转,先对4节点的左子树进行左旋操作,然后再对节点4进行右旋操作。
判断进行RL操作还是进行RR操作是看要进行右旋操作的树的左子树是右重还是左重。右重即树的右子树高度大于左子树。如果要进行右旋操作的树的左子树是右重,则进行RL操作,否则进行RR操作。
LL
如图5所示,LL操作和RR操作对称。
LR
如图6所示LR操作和RL操作对称。
AVL树的实现
#if !defined(AFX_AVLTREE_H__D78D2C76_87EF_4B00_9AF7_C2FF4076B620__INCLUDED_)
#define AFX_AVLTREE_H__D78D2C76_87EF_4B00_9AF7_C2FF4076B620__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class AVLTree;
typedef AVLTree* AVLTreePtr;
class AVLTree
{
public:
AVLTree();
virtual ~AVLTree();
static AVLTreePtr Delete(AVLTreePtr tree,int data);
static void Dump(AVLTreePtr tree);
static void Test();
static AVLTreePtr Insert(AVLTreePtr tree,int data);
public:
AVLTreePtr m_left,m_right;
int m_data;
int m_height;
private:
static AVLTreePtr FindMin(AVLTreePtr tree);
static AVLTreePtr DeleteData(AVLTreePtr tree, int data);
static int Height(AVLTreePtr tree);
static AVLTreePtr InsertData(AVLTreePtr tree,AVLTreePtr parent,int data);
static AVLTreePtr RightLeft(AVLTreePtr tree);
static AVLTreePtr LeftRight(AVLTreePtr tree);
static AVLTreePtr LeftLeft(AVLTreePtr tree);
static AVLTreePtr RightRight(AVLTreePtr tree);
static void Output(AVLTreePtr tree);
};
#endif // !defined(AFX_AVLTREE_H__D78D2C76_87EF_4B00_9AF7_C2FF4076B620__INCLUDED_)
#include "stdafx.h"
#include "AVLTree.h"
#include <assert.h>
//#include <stdio.h>
//#include <math.h>
//#include <stdlib.h>
#define max(a,b) (a)<(b)?(b):(a)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
AVLTree::AVLTree()
{
m_left=m_right=NULL;
m_height=0;
}
AVLTree::~AVLTree()
{
}
AVLTreePtr AVLTree::Insert(AVLTreePtr tree,int data)
{
bool inserted=false;
tree=InsertData(tree,NULL,data);
return tree;
}
AVLTreePtr AVLTree::InsertData(AVLTreePtr tree, AVLTreePtr parent,int data)
{
AVLTreePtr nodePtr,rotateTree;
int lHeight,rHeight,lSubHeight,rSubHeight;
if(NULL==tree)
{
nodePtr=new AVLTree;
nodePtr->m_data=data;
nodePtr->m_height=0;
return nodePtr;
}
rotateTree=tree;
if(data<tree->m_data)
{
tree->m_left=InsertData(tree->m_left,tree,data);
lHeight=Height(tree->m_left);
rHeight=Height(tree->m_right);
if(rHeight-lHeight==-2)
{
lSubHeight=Height(tree->m_left->m_left);
rSubHeight=Height(tree->m_left->m_right);
if(lSubHeight>rSubHeight)
{
rotateTree=RightRight(tree);
}
else
{
rotateTree=RightLeft(tree);
}
}
}
else if(data>tree->m_data)
{
tree->m_right=InsertData(tree->m_right,tree,data);
lHeight=Height(tree->m_left);
rHeight=Height(tree->m_right);
if(rHeight-lHeight==2)
{
lSubHeight=Height(tree->m_right->m_left);
rSubHeight=Height(tree->m_right->m_right);
if(lSubHeight<rSubHeight)
{
rotateTree=LeftLeft(tree);
}
else
{
rotateTree=LeftRight(tree);
}
}
}
else
{
assert(false);
}
lHeight=Height(rotateTree->m_left);
rHeight=Height(rotateTree->m_right);
rotateTree->m_height=1+max(lHeight,rHeight);
if(parent!=NULL)
{
if(parent->m_left==tree)
{
parent->m_left=rotateTree;
}
else
{
parent->m_right=rotateTree;
}
}
return rotateTree;
}
AVLTreePtr AVLTree::Delete(AVLTreePtr tree, int data)
{
return DeleteData(tree,data);
}
AVLTreePtr AVLTree::DeleteData(AVLTreePtr tree, int data)
{
AVLTreePtr nodePtr;
int lHeight,rHeight,lSubHeight,rSubHeight;
if(NULL==tree) return NULL;
if(data<tree->m_data)
{
tree->m_left = DeleteData(tree->m_left,data);
}
else if(data>tree->m_data)
{
tree->m_right = DeleteData(tree->m_right,data);
}
else
{
if(tree->m_left && tree->m_right)
{
nodePtr=FindMin(tree->m_right);
tree->m_data=nodePtr->m_data;
tree->m_right=DeleteData(tree->m_right,nodePtr->m_data);
}
else if(tree->m_left)
{
nodePtr=tree;
tree=tree->m_left;
delete nodePtr;
}
else if(tree->m_right)
{
nodePtr=tree;
tree=tree->m_right;
delete nodePtr;
}
else
{
delete tree;
tree=NULL;
}
}
if(NULL==tree) return NULL;
lHeight=Height(tree->m_left);
rHeight=Height(tree->m_right);
if(rHeight-lHeight==-2)
{
lSubHeight=Height(tree->m_left->m_left);
rSubHeight=Height(tree->m_left->m_right);
if(lSubHeight>rSubHeight)
{
tree=RightRight(tree);
}
else
{
tree=RightLeft(tree);
}
}
else if(rHeight-lHeight==2)
{
lSubHeight=Height(tree->m_right->m_left);
rSubHeight=Height(tree->m_right->m_right);
if(lSubHeight<rSubHeight)
{
tree=LeftLeft(tree);
}
else
{
tree=LeftRight(tree);
}
}
lHeight=Height(tree->m_left);
rHeight=Height(tree->m_right);
tree->m_height=1+max(lHeight,rHeight);
return tree;
}
AVLTreePtr AVLTree::FindMin(AVLTreePtr tree)
{
if(NULL==tree) return NULL;
if(tree->m_left) return FindMin(tree->m_left);
return tree;
}
int AVLTree::Height(AVLTreePtr tree)
{
if(NULL==tree) return -1;
int lHeight=Height(tree->m_left);
int rHeight=Height(tree->m_right);
int h=lHeight>rHeight?lHeight:rHeight;
return h+1;
}
AVLTreePtr AVLTree::RightRight(AVLTreePtr tree)
{
AVLTreePtr subNode=tree->m_left;
tree->m_left=subNode->m_right;
subNode->m_right=tree;
int lHeight,rHeight;
lHeight=Height(subNode->m_left);
rHeight=Height(subNode->m_right);
subNode->m_height=1+max(lHeight,rHeight);
lHeight=Height(tree->m_left);
rHeight=Height(tree->m_right);
tree->m_height=1+max(lHeight,rHeight);
return subNode;
}
AVLTreePtr AVLTree::LeftLeft(AVLTreePtr tree)
{
AVLTreePtr subNode=tree->m_right;
tree->m_right=subNode->m_left;
subNode->m_left=tree;
int lHeight,rHeight;
lHeight=Height(subNode->m_left);
rHeight=Height(subNode->m_right);
subNode->m_height=1+max(lHeight,rHeight);
lHeight=Height(tree->m_left);
rHeight=Height(tree->m_right);
tree->m_height=1+max(lHeight,rHeight);
return subNode;
}
AVLTreePtr AVLTree::RightLeft(AVLTreePtr tree)
{
AVLTreePtr subNode=tree->m_left;
tree->m_left = LeftLeft(subNode);
return RightRight(tree);
}
AVLTreePtr AVLTree::LeftRight(AVLTreePtr tree)
{
AVLTreePtr subNode=tree->m_right;
tree->m_right=RightRight(subNode);
return LeftLeft(tree);
}
void AVLTree::Output(AVLTreePtr tree)
{
if(NULL==tree) return;
printf("(");
if(tree->m_left)
{
Output(tree->m_left);
}
else
{
printf("*,");
}
printf("%d,",tree->m_data);
if(tree->m_right)
{
Output(tree->m_right);
}
else
{
printf("*");
}
printf(")");
}
void AVLTree::Dump(AVLTreePtr tree)
{
Output(tree);
printf("/n");
}
void AVLTree::Test()
{
AVLTreePtr tree=NULL;
tree=Insert(tree,9);
Dump(tree);
tree=Insert(tree,7);
Dump(tree);
tree=Insert(tree,10);
Dump(tree);
tree=Insert(tree,8);
Dump(tree);
tree=Delete(tree,10);
Dump(tree);
}