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

数据结构——AVL树(平衡二叉树)的详细实现

2017-07-29 10:58 627 查看
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 <iostream>
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;
}


运行结果如下:

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