github地址:https://github.com/lining91/AVLTree
AVL树的介绍:
AVL树的必要条件:
1、必须是二叉查找树
2、每个节点的左子树和右子树的高度差至多为1。
图一:非平衡二叉树
图一:非平衡二叉树中节点26的左子树高度为2,右子树高度为0,左右子树差为2。所以是非平衡二叉树。
AVL树的查找、插入、删除操作在平均和最坏的情况下都是O(logn)。
不平衡的二叉查找树在查找时效率比较低。如果需要查找的数据集合本身没有顺序,在频繁的查找的同时也经常的插入和删除的时候,AVL树是不错的选择。
相关概念:
1、平衡因子
将二叉树上节点的左子树减去右子树高度的值,称为该节点的平衡因子BF。
对于平衡二叉树,BF取值范围为[-1, 1]。对于不在此范围的树需要进行调整。
2、最小不平衡子树
距离插入节点最近的,且平衡因子的绝对值大于1的节点为根的子树。
插入新节点倒是失衡调整:
1、左单旋转
向右子树插入右孩子导致AVL失衡时,需要围绕最小失衡子树的根节点进行左单旋转。
对应接口是LeftRotaion。
2、右单旋转
向左子树插入左孩子导致AVL失衡时,需要围绕最小失衡子树的根节点进行右单旋转。
对应接口是RightRotation。
3、先左旋后右旋
在左子树上插入右孩子导致AVL树失衡时,需要进行先左旋后右旋。
对应接口是LeftRightRotation。
4、先右旋后左旋
在右子树上插入左孩子导致AVL树失衡时,需要进行先右旋后左旋。
对应接口是RightLeftRotation。
删除节点:
1、删除右子树的节点
删除右子树的节点导致AVL树失衡,相当于在左子树插入新节点导致AVL树失衡,应进行右单旋转或先右旋后左旋。
2、删除左子树的节点
删除左子树的节点导致AVL树失衡,相当于在右子树插入新节点导致AVL树失衡,应进行左单旋转或者先左旋后右旋。
查找元素:
可以使用递归和非递归两种方法查询对应的元素。
遍历:
分为先序遍历、中序遍历、后序遍历。
代码如下:
#include
using namespace std;
struct AVLTreeNode{
public:
int key; // 关键字(键值)
int nHeight; // 高度
AVLTreeNode *pLeftChild; // 左孩子节点
AVLTreeNode *pRightChild; // 右孩子节点
AVLTreeNode( int value, AVLTreeNode *l, AVLTreeNode *r ) : key(value), nHeight(0),pLeftChild(l),pRightChild(r)
{
}
};
class AVLTree
{
public:
AVLTree();
~AVLTree();
void Preorder(); // 前序遍历
void Inorder(); // 中序遍历
void Postorder(); // 后序遍历
void Insert( int key ); // 插入指定值的节点
void Delete( int key ); // 删除指定值的节点
void Destroy(); // 销毁AVL树
const int GetMiniNum(); // 返回AVL树中的最小值
const int GetMaxNum(); // 返回AVL树中的最大值
const int GetHeight(); // 获取AVL树的高度
AVLTreeNode* SearchRecurse( int key ); // 查找指定值(使用递归进行)
AVLTreeNode* Search( int key ); // 查找指定值(使用迭代器进行)
private:
void Preorder( AVLTreeNode* pNode ) const; // 前序遍历
void Inorder( AVLTreeNode* pNode ) const; // 中序遍历
void Postorder( AVLTreeNode* pNode ) const; // 后序遍历
AVLTreeNode* Delete( AVLTreeNode* &pNode, int key ); // 删除AVL树中节点pDel,并返回被删除的节点
void Destroy( AVLTreeNode* &pNode);
AVLTreeNode* GetMiniNum( AVLTreeNode* pNode ) const;
AVLTreeNode* GetMaxNum( AVLTreeNode* pNode ) const;
int GetHeight( AVLTreeNode* pNode );
AVLTreeNode* SearchRecurse( AVLTreeNode* pNode, int key ) const;
AVLTreeNode* Search( AVLTreeNode* pNode, int key ) const;
AVLTreeNode* LeftRotaion( AVLTreeNode* pNode ); // 左旋操作(单旋),返回旋转后的根节点
AVLTreeNode* RightRotation( AVLTreeNode* pNode ); // 右旋操作(单旋),返回旋转后的根节点
AVLTreeNode* LeftRightRotation( AVLTreeNode* pNode ); // 先左旋操作,后右旋操作(双旋),返回旋转后的根节点
AVLTreeNode* RightLeftRotation( AVLTreeNode* pNode ); // 先右旋操作,后左旋操作(双旋),返回旋转后的根节点
AVLTreeNode* Insert( AVLTreeNode* &pNode, int key );
private:
AVLTreeNode* pRoot;
};
AVLTree::AVLTree( ) : pRoot( NULL )
{}
AVLTree::~AVLTree( )
{
Destroy( pRoot );
}
void AVLTree::Preorder()
{
Preorder( pRoot );
}
void AVLTree::Preorder( AVLTreeNode* pNode ) const
{
if ( pNode != NULL )
{
cout << " " << pNode->key << " " ;
Preorder( pNode->pLeftChild );
Preorder( pNode->pRightChild );
}
}
void AVLTree::Inorder()
{
Inorder( pRoot );
}
void AVLTree::Inorder( AVLTreeNode* pNode ) const
{
if ( pNode != NULL )
{
Inorder( pNode->pLeftChild );
cout << " " << pNode->key << " " ;
Inorder( pNode->pRightChild );
}
}
void AVLTree::Postorder()
{
Postorder( pRoot );
}
void AVLTree::Postorder( AVLTreeNode* pNode ) const
{
if ( pNode != NULL )
{
Postorder( pNode->pLeftChild );
Postorder( pNode->pRightChild );
cout << " " << pNode->key << " " ;
}
}
void AVLTree::Destroy()
{
Destroy( pRoot );
}
void AVLTree::Destroy( AVLTreeNode* &pNode)
{
if ( pNode == NULL )
return;
Destroy( pNode->pLeftChild );
Destroy( pNode->pRightChild );
delete pNode;
pNode = NULL;
}
void AVLTree::Insert( int key )
{
Insert( pRoot, key );
}
AVLTreeNode* AVLTree::Insert( AVLTreeNode* &pNode, int key )
{
if ( pNode == NULL )
pNode = new AVLTreeNode( key, NULL, NULL );
else if ( pNode->key > key ) // 插入值比当前节点的值小,插入到当前节点的左子树
{
pNode->pLeftChild = Insert( pNode->pLeftChild, key );
if ( GetHeight( pNode->pLeftChild) - GetHeight( pNode->pRightChild ) == 2 )
{
if ( key < pNode->pLeftChild->key ) // 插入到左子树的左孩子节点上,进行右旋
pNode = RightRotation( pNode );
else if ( key > pNode->pLeftChild->key ) // 插入到左子树的左孩子节点上,进行先左旋后右旋
pNode = LeftRightRotation( pNode );
}
}
else if ( pNode->key < key ) // 插入值比当前节点的值大,插入到当前节点的右子树
{
pNode->pRightChild = Insert( pNode->pRightChild, key );
if ( GetHeight( pNode->pRightChild ) - GetHeight( pNode->pLeftChild ) == 2 )
{
if ( key > pNode->pRightChild->key ) // 插入到右子树的右节点上,进行左旋
pNode = LeftRotaion( pNode );
else if ( key < pNode->pRightChild->key )
pNode = LeftRightRotation( pNode );
}
}
pNode->nHeight = max( GetHeight( pNode->pLeftChild ), GetHeight( pNode->pRightChild ) ) + 1;
return pNode;
}
void AVLTree::Delete( int key )
{
pRoot = Delete( pRoot, key );
}
AVLTreeNode* AVLTree::Delete( AVLTreeNode* &pNode, int key )
{
if ( pNode == NULL )
return NULL;
if ( key == pNode->key ) // 找到要删除的节点
{
if ( pNode->pLeftChild != NULL && pNode->pRightChild != NULL )
{
// 左子树比右子树高,在左子树上选择节点进行替换
if ( GetHeight( pNode->pLeftChild ) > GetHeight( pNode->pRightChild ) )
{
// 使用左子树的最大节点来代替被删节点,而删除该最大节点
AVLTreeNode* pNodeTemp = GetMaxNum( pNode->pLeftChild ); // 左子树最大节点
pNode->key = pNodeTemp->key;
pNode->pLeftChild = Delete( pNode->pLeftChild, pNodeTemp->key ); // 递归地删除最大节点
}
else
{
// 使用最小节点来代替被删节点,而删除该最小节点
AVLTreeNode* pNodeTemp = GetMiniNum( pNode->pRightChild ); // 右子树的最小节点
pNode->key = pNodeTemp->key;
pNode->pRightChild = Delete( pNode->pRightChild, pNodeTemp->key ); // 递归地删除最小节点
}
}
else
{
AVLTreeNode* pNodeTemp = pNode;
if ( pNode->pLeftChild != NULL )
pNode = pNode->pLeftChild;
if ( pNode->pRightChild != NULL )
pNode = pNode->pRightChild;
delete pNodeTemp;
pNodeTemp = NULL;
return pNode;
}
}
else if ( key > pNode->key ) // 要删除的节点比当前结点大,则在右子树进行查找
{
pNode->pRightChild = Delete( pNode->pRightChild, key );
if ( GetHeight( pNode->pLeftChild ) - GetHeight( pNode->pRightChild ) == 2 )
{
if ( GetHeight( pNode->pLeftChild->pRightChild ) > GetHeight( pNode->pLeftChild->pLeftChild ) )
pNode = LeftRightRotation( pNode );
else
pNode = RightRotation( pNode );
}
}
else // 要删除的节点比当前结点小,则在左子树进行查找
{
pNode->pLeftChild = Delete( pNode->pLeftChild, key );
if ( GetHeight( pNode->pLeftChild->pRightChild ) > GetHeight( pNode->pLeftChild->pLeftChild ) )
pNode = RightLeftRotation( pNode );
else
pNode = LeftRotaion( pNode );
}
return pNode;
}
const int AVLTree::GetMiniNum()
{
AVLTreeNode* pFindNode = GetMiniNum( pRoot );
if ( pFindNode == NULL )
return 0;
return pFindNode->key;
}
AVLTreeNode* AVLTree::GetMiniNum( AVLTreeNode* pNode ) const
{
if ( pNode == NULL )
return NULL;
while ( pNode->pLeftChild != NULL )
pNode = pNode->pLeftChild;
return pNode;
}
const int AVLTree::GetMaxNum()
{
AVLTreeNode* pFindNode = GetMaxNum( pRoot );
if ( pFindNode == NULL )
return 0;
return pFindNode->key;
}
AVLTreeNode* AVLTree::GetMaxNum( AVLTreeNode* pNode ) const
{
if ( pNode == NULL )
return NULL;
while ( pNode->pRightChild != NULL )
pNode = pNode->pRightChild;
return pNode;
}
const int AVLTree::GetHeight()
{
return GetHeight( pRoot );
}
int AVLTree::GetHeight( AVLTreeNode* pNode )
{
if ( pNode == NULL )
return 0;
return pNode->nHeight;
}
AVLTreeNode* AVLTree::SearchRecurse( int key )
{
return SearchRecurse( pRoot, key );
}
AVLTreeNode* AVLTree::SearchRecurse( AVLTreeNode* pNode, int key ) const
{
if ( pNode == NULL )
return NULL;
if ( key == pNode->key )
return pNode;
if ( key > pNode->key )
return SearchRecurse( pNode->pRightChild, key);
else
return SearchRecurse( pNode->pLeftChild, key);
}
AVLTreeNode* AVLTree::Search( int key )
{
return Search( pRoot, key );
}
AVLTreeNode* AVLTree::Search( AVLTreeNode* pNode, int key ) const
{
while ( pNode != NULL )
{
if ( key == pNode->key )
return pNode;
if ( key > pNode->key )
pNode = pNode->pRightChild;
else
pNode = pNode->pLeftChild;
}
return NULL;
}
AVLTreeNode* AVLTree::LeftRotaion( AVLTreeNode* pNode )
{
AVLTreeNode* pRChlid = pNode->pRightChild;
pNode->pRightChild = pRChlid->pLeftChild;
pRChlid->pLeftChild = pNode;
pNode->nHeight = max( GetHeight( pNode->pLeftChild ), GetHeight( pNode->pRightChild ) ) + 1 ;
pRChlid->nHeight = max( GetHeight( pRChlid->pLeftChild ), GetHeight( pRChlid->pRightChild ) ) + 1 ;
return pRChlid;
}
AVLTreeNode* AVLTree::RightRotation( AVLTreeNode* pNode )
{
AVLTreeNode* pLChild = pNode->pLeftChild;
pNode->pLeftChild = pLChild->pRightChild;
pLChild->pRightChild = pNode;
pNode->nHeight = max( GetHeight( pNode->pLeftChild ), GetHeight( pNode->pRightChild ) ) + 1 ;
pLChild->nHeight = max( GetHeight( pLChild->pLeftChild ), GetHeight( pLChild->pRightChild ) ) + 1 ;
return pLChild;
}
AVLTreeNode* AVLTree::LeftRightRotation( AVLTreeNode* pNode )
{
pNode->pRightChild = RightRotation( pNode->pRightChild );
return LeftRotaion( pNode );
}
AVLTreeNode* AVLTree::RightLeftRotation( AVLTreeNode* pNode )
{
pNode->pLeftChild = LeftRotaion( pNode->pLeftChild );
return RightRotation( pNode );
}
void main( )
{
AVLTree* pTree = new AVLTree( );
for ( int nIdx = 0; nIdx < 10; nIdx++ )
{
pTree->Insert( nIdx );
}
cout << " 树的高度为:" << pTree->GetHeight( ) << endl;
cout << " 前序遍历:" ;
pTree->Preorder( );
cout << endl;
cout << " 中序遍历:" ;
pTree->Inorder( );
cout << endl;
cout << " 后序遍历:" ;
pTree->Postorder( );
cout << endl;
int nDeleteKey = 8;
AVLTreeNode* pFindNode = pTree->SearchRecurse( nDeleteKey );
if ( pFindNode == NULL )
cout << " 无元素" << nDeleteKey << endl;
else
{
cout << " 删除元素" << nDeleteKey << endl;
pTree->Delete( nDeleteKey );
cout << " 前序遍历:" ;
pTree->Preorder( );
}
cout << endl;
system( "pause");
return;
}