数据结构——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树失衡,应进行左单旋转或者先左旋后右旋。
查找元素:
可以使用递归和非递归两种方法查询对应的元素。
遍历:
分为先序遍历、中序遍历、后序遍历。
代码如下:
运行结果如下:
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; }
运行结果如下:
相关文章推荐
- java实现AVL树(一种自平衡二叉树)数据结构
- java数据结构与算法之平衡二叉树(AVL树)的设计与实现
- C++数据结构: 顺序表 详细实现
- 【数据结构】平衡二叉树之AVL树
- java数据结构与算法之平衡二叉树(AVL树)的设计与实现
- AVL树(平衡二叉树)及其实现
- 数据结构之 AVL树(平衡二叉树)(C语言实现)
- 【数据结构】平衡二叉树之AVL树
- 平衡二叉树的C语言实现(创建、插入、查找、删除、旋转)【数据结构】
- 数据结构 — AVL树(平衡二叉树)
- PHP实现平衡二叉树(AVL树)
- 平衡二叉树的实现代码加详细注释
- 数据结构:AVL树(平衡二叉树)
- 平衡二叉树(AVL树)的简单实现
- 自己动手实现数据结构——AVL树(C++实现)
- 【数据结构】AVL树的实现
- 平衡二叉树的实现原理(代码实现)- 数据结构和算法78
- 数据结构学习之用Java实现AVL树
- 【数据结构】树(二):二叉树&二叉搜索树&平衡二叉树(C++实现)
- 【数据结构】平衡二叉树[AVL树](二)——删除