首页 > 代码库 > C++模板实现的AVL树
C++模板实现的AVL树
1 AVL树的定义
AVL树是一种自平衡二叉排序树,它的特点是任何一个节点的左子树高度和右子树的高度差在-1,0,1三者之间。AVL树的任何一个子树都是AVL树。
2 AVL树的实现
AVL树本质是一种二叉排序树,所以二叉排序树的任何性质AVL树都具有,但是AVL树稍微复杂的地方就是AVL树必须满足平衡条件,具体跟BST不同的地方主要体现在插入,删除操作。
插入操作:当插入之后可能会出现不平衡,所以这时候要通过旋转树来实现平衡。旋转有四种类型,左左,左右,右左,右右。其中左左旋转和右右旋转是镜像的,左右旋转和右左旋转是镜像的,所以实质上就是两种类型的旋转。针对左左旋转,只需要旋转一次即可,针对左右旋转,需要执行两次旋转。见下图:
这里采用递归法实现插入和删除操作。使用递归方便的一点是如果函数的参数是引用类型的,当传入一个p->left的时候,我们在当前函数的下层递归的时候,对p进行的赋值操作其实就是对上层递归中的p->left进行的操作,所以这样就不需要传递父指针了。
3 实现代码
//AVLTree.h
#ifndef DDXX_AVLTREE_H #define DDXX_AVLTREE_H #include <iostream> #include <queue> using namespace std; template<typename Type> class AVLTree { struct Node { Type e; Node* left; Node* right; int h; Node(Type _e):e(_e),left(NULL),right(NULL),h(0){} Node(Type _e,Node* _left,Node* _right,int _h):e(e),left(_left),right(_right),h(_h){} }; public: AVLTree(); AVLTree(Type arr[],int nLength); /*AVLTree(const AVLTree& right); AVLTree& operator=(const AVLTree& right);*/ ~AVLTree(); public: bool insert(Type e,Node* &p); void erase(Type e,Node* &p); Node*& find(Type e)const; void traverse(Node* p)const; void traverseByLevel(Node* p)const; int getLength(){return mLength;} Node*& getParent(Node* p); Node*& getRoot(){return mRoot;} //notice the return type bool empty(){return mRoot==NULL;}; void clear(); void clears(Node* &p); private: void rotateLeft(Node* &k2); void rotateRight(Node* &k2); void rotateLeftDouble(Node* &p); void rotateRightDouble(Node* &p); int height(Node* p)const{ return p == NULL ? -1 : p->h ;} int max(int x,int y){return x>y?x:y;} private: Node* mRoot; int mLength; }; template<typename Type> AVLTree<Type>::AVLTree():mRoot(NULL),mLength(0) { } template<typename Type> AVLTree<Type>::AVLTree(Type arr[],int nLength):mRoot(NULL),mLength(0) { for(int i=0;i<nLength;i++) { insert(arr[i],mRoot); } } template<typename Type> AVLTree<Type>::~AVLTree() { clears(mRoot); } template<typename Type> bool AVLTree<Type>::insert(Type e,Node* &p) { if( p== NULL) { p = new Node(e); mLength++; } else if(e < p->e) { insert(e,p->left); if( height(p->left) - height(p->right) == 2) { if (e < p->left->e) rotateLeft(p); else rotateLeftDouble(p); } } else if(e > p->e) { insert(e,p->right); if( height(p->left) - height(p->right) == -2) { if (e > p->right->e) rotateRight(p); else rotateRightDouble(p); } } else // e ia already exist { //return false; } p->h = max( height(p->left),height(p->right) )+1; return true; } template<typename Type> void AVLTree<Type>::rotateLeft(Node*& k2) { Node* k1 = k2->left; k2->left = k1->right; k1->right = k2; k1->h = max( height(k1->left),height(k1->right) ) + 1; k2->h = max( height(k2->left),height(k2->right) ) + 1; k2 = k1;// join the original node } template<typename Type> void AVLTree<Type>::rotateRight(Node* &k2) { Node* k1 = k2->right; k2->right = k1->left; k1->left = k2; k1->h = max( height(k1->left),height(k1->right) ) + 1; k2->h = max( height(k2->left),height(k2->right) ) + 1; //k1=k2,因为在insert函数中传入的是p->left或者p->right的引用,所以这里能把根结点赋给其父结点的子节点 k2 = k1; } template<typename Type> void AVLTree<Type>::rotateLeftDouble(Node*& k3) { rotateRight(k3->left); rotateLeft(k3); } template<typename Type> void AVLTree<Type>::rotateRightDouble(Node*& k3) { rotateLeft(k3->right); rotateRight(k3); } template<typename Type> void AVLTree<Type>::traverse(Node* p)const { if( p == NULL) return; else { traverse(p->left); cout<<"element:"<<p->e<<endl; //traverse by mid traverse(p->right); } } template<typename Type> void AVLTree<Type>::traverseByLevel(Node* root)const { if(root == NULL) { cout<<"The tree is empty"<<endl; return; } queue<Node*> que; que.push(root); while( !que.empty() ) { Node* ptr = que.front(); que.pop(); cout<<"element:"<<ptr->e<<" th:"<<height(ptr->left) - height(ptr->right)<<endl; if(ptr->left != NULL) que.push(ptr->left); if(ptr->right != NULL) que.push(ptr->right); } } template<typename Type> typename AVLTree<Type>::Node* & AVLTree<Type>::getParent(Node* p) { if( p == m_root) return NULL; Node* ptr = m_root; Node* ptf = ptr; while( ptr != NULL ) { if ( ptr->e == p->e ) return ptf; if ( ptr->e > p->e ) { ptf = ptr; ptr = ptr->leftChild; } else { ptf = ptr; ptr = ptr->rightChild; } } } template<typename Type> typename AVLTree<Type>::Node*& AVLTree<Type>::find(Type e)const { Node* ptr = m_root; while(ptr != NULL) { if ( ptr->e == e ) return ptr; if ( ptr->e > e ) ptr = ptr->leftChild; else ptr = ptr->rightChild; } //if ( ptr == NULL ) return NULL; } template<typename Type> void AVLTree<Type>::clears(Node*& p) { if( p == NULL ) return; else { clears(p->left); clears(p->right); delete p; p = NULL; mLength--; } } template<typename Type> void AVLTree<Type>::clear() { clears(mRoot); } template<typename Type> void AVLTree<Type>::erase(Type e,Node* &p) { if( p == NULL) return; if( e > p->e) { erase(e,p->right); if( height(p->left) - height(p->right) == 2) { if( height(p->left->left) > height(p->left->right) ) rotateLeft(p); else rotateLeftDouble(p); } } else if( e < p->e) { erase(e,p->left); if( height(p->left) - height(p->right) == -2) { if( height(p->right->right) > height(p->right->left) ) rotateRight(p); else rotateRightDouble(p); } } else if ( e == p->e && p->left!= NULL && p->right!= NULL) { Node* pmax = p->left; while( pmax->right != NULL) { pmax = pmax->right; } p->e = pmax->e; erase(p->e,p->left); } else //最终的删除会在这里执行 { Node* pNew = p->left==NULL ? p->right : p->left; delete p; p = pNew; mLength--; } if ( p!=NULL) p->h = max( height(p->left),height(p->right)) + 1; } #endif
//main.cpp
#include <iostream> #include "AVLTree.h" using namespace std; void main() { int Arr[9] = {6,2,8,4,10,0,12,16,14}; AVLTree<int> Tr(Arr,9); Tr.traverse(Tr.getRoot()); Tr.traverseByLevel(Tr.getRoot()); Tr.erase(14,Tr.getRoot()); Tr.traverse(Tr.getRoot()); Tr.traverseByLevel(Tr.getRoot()); cout<<"Tree's length is:"<<Tr.getLength()<<endl; Tr.clear(); cout<<"Tree's length is:"<<Tr.getLength()<<endl; }
4 测试结果
C++模板实现的AVL树
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。