C++ AVL平衡树 模板

来源:互联网 发布:js中数字转化成字符串 编辑:程序博客网 时间:2024/06/04 18:55

在上篇博文中的二叉搜索树的基础上(无实际联系,只是当时开发的时候参考),实现了AVL平衡树,完美地实现了其中较为困难的旋转操作。使用请注明出处,谢谢。

源代码如下:

#pragma once//#include "STree.h"template <class T> class AVLTree;template<class T, class Ref=T&, class Ptr=T*> class AVLTree_iterator;template<class T, class Ref=T&, class Ptr=T*> class AVLTree_const_iterator;template <class T>class AVLNode {friend class AVLTree<T>;friend class AVLTree_iterator<T>;friend class AVLTree_const_iterator<T>;protected:T data;AVLNode<T> *left, *right, *parent;int factor;//factor=height(right subtree)-height(left subtree)void copy(const AVLNode<T> &rhs) {//if(rhs==NULL) {cout<<"error: no source"<<endl; return;}left=rhs.left;right=rhs.right;parent=rhs.parent;data=rhs.data;factor=rhs.factor;}public:AVLNode() {left=NULL, right=NULL, parent=NULL;factor=0;}AVLNode(const T &item, AVLNode<T> *lptr=NULL, AVLNode<T> *rptr=NULL, AVLNode<T> *pptr=NULL, int ftor=0 ):data(item), left(lptr), right(rptr), parent(pptr), factor(ftor) {}~AVLNode() {}AVLNode(const AVLNode<T> &rhs) { copy(rhs);}AVLNode &operator=(const AVLNode<T> &rhs) { copy(rhs); return *this; }int Factor() { return factor; }};template <class T>class AVLTree {enum {AVLL=-1, AVLB=0, AVLR=1 };// Balance state information stored in each node in AVL tree. friend class AVLTree_iterator<T>;friend class AVLTree_const_iterator<T>;protected:AVLNode<T> *root;int size;AVLNode<T> *GetNode(const T &item, AVLNode<T> *lptr, AVLNode<T> *rptr, AVLNode<T> *pptr, int ftor=0) {AVLNode<T> *newnode=new AVLNode<T>(item, lptr, rptr, pptr, ftor);if( newnode==NULL ) {cerr<<"allocate storage for new node failed!"<<endl; exit(0);}return newnode;}AVLNode<T> *copy(AVLNode<T> *rhs) {AVLNode<T> *lptr=NULL, *rptr=NULL, newnode=NULL;int ftor=0;if(rhs==NULL) return NULL;lptr=copy(rhs->left);rptr=copy(rhs->right);newnode=GetNode(rhs->data, lptr, rptr, NULL, rhs->factor);if(lptr!=NULL) lptr->parent=newnode;if(rptr!=NULL) rptr->parent=newnode;return newnode;}void DelTree(AVLNode<T> *_root) {if(_root==NULL) return;DelTree(_root->left);DelTree(_root->right);delete _root;}AVLNode<T> *findNode(const T& item) const {//only the type of its return value is different  //with its base class, polymorphism can not be realizedAVLNode<T> *cur=root;while(cur!=NULL) {if(cur->data==item) return cur;else if(cur->data<item) cur=cur->right;else cur=cur->left;}return cur;}void SingleRotateRight(AVLNode<T> * &cur) {AVLNode<T> *leftchild=cur->left;AVLNode<T> *par=cur->parent;//after the adjustment, all the nodes will be balancedleftchild->factor=AVLB;cur->factor=AVLB;cur->left=leftchild->right; //the original right subtree of the the leftchild will move to the left subtree of its original parentif(cur->left!=NULL) cur->left->parent=cur;leftchild->right=cur;//the new right subtree of the new root should be its original parentcur->parent=leftchild;leftchild->parent=par;cur=leftchild;              //leftchild now is the new root}void DoubleRotateRight(AVLNode<T> * &cur) {AVLNode<T> *leftchild=cur->left;AVLNode<T> *lc_rht_chd=leftchild->right;AVLNode<T> *par=cur->parent;//after the adjustment, the balance factor should like thisif(lc_rht_chd->factor==AVLR) {cur->factor=AVLB;leftchild->factor=AVLL;}else if(lc_rht_chd->factor==AVLB) {cur->factor=AVLB;leftchild->factor=AVLB;}else {cur->factor=AVLR;leftchild->factor=AVLB;}lc_rht_chd->factor=AVLB;//rotationleftchild->right=lc_rht_chd->left;if(lc_rht_chd->left!=NULL) lc_rht_chd->left->parent=leftchild;lc_rht_chd->left=leftchild;leftchild->parent=lc_rht_chd;cur->left=lc_rht_chd->right;if(lc_rht_chd->right!=NULL) lc_rht_chd->right->parent=cur;lc_rht_chd->right=cur;cur->parent=lc_rht_chd;cur=lc_rht_chd;lc_rht_chd->parent=par;}void SingleRotateLeft(AVLNode<T> * &cur) {AVLNode<T> *rightchild=cur->right;AVLNode<T> *par=cur->parent;rightchild->factor=AVLB;cur->factor=AVLB;cur->right=rightchild->left;if(cur->right!=NULL) cur->right->parent=cur;rightchild->left=cur;cur->parent=rightchild;rightchild->parent=par;cur=rightchild;}void DoubleRotateLeft(AVLNode<T> * &cur) {AVLNode<T> *rightchild=cur->right;AVLNode<T> *rc_left_chd=rightchild->left;AVLNode<T> *par=cur->parent;if(rc_left_chd->factor==AVLR) {cur->factor=AVLL;rightchild->factor=AVLB;}else if(rc_left_chd->factor==AVLB) {cur->factor=AVLB;rightchild->factor=AVLB;}else {cur->factor=AVLB;rightchild->factor=AVLR;}rc_left_chd->factor=AVLB;rightchild->left=rc_left_chd->right;if(rc_left_chd->right!=NULL) rc_left_chd->right->parent=rightchild;rc_left_chd->right=rightchild;rightchild->parent=rc_left_chd;cur->right=rc_left_chd->left;if(rc_left_chd->left!=NULL) rc_left_chd->left->parent=cur;rc_left_chd->left=cur;cur->parent=rc_left_chd;cur=rc_left_chd;rc_left_chd->parent=par;}void UpdateLeft(AVLNode<T> * &cur, bool &revise_bfactor) {AVLNode<T> *leftchild=cur->left;if(leftchild->factor==AVLL) {//left subtree is heavierSingleRotateRight(cur);revise_bfactor=false;}else if(leftchild->factor==AVLR) {DoubleRotateRight(cur);revise_bfactor=false;}else {//error message}}void UpdateRight(AVLNode<T> * &cur, bool &revise_bfactor) {AVLNode<T> *rightchild=cur->right;if(rightchild->factor==AVLR) {SingleRotateLeft(cur);revise_bfactor=false;}else if(rightchild->factor==AVLL) {DoubleRotateLeft(cur);revise_bfactor=false;}else {//error message}}AVLNode<T> *AVLinsert(AVLNode<T> * &cur, AVLNode<T> *newnode, AVLNode<T> *par, bool &revise_bfactor){bool sub_rebfactor=false;   //denotes if the balance of the subtree was destroiedif(cur==NULL) {   //a empty subtree is encountered, insert the newnodecur=newnode;cur->parent=par;cur->factor=AVLB;revise_bfactor=true;}else if(newnode->data < cur->data) {//insert to the left subtreepar=cur;AVLinsert(cur->left, newnode, par, sub_rebfactor);if(sub_rebfactor) {//the balance of the left subtree is changedif(cur->factor==AVLL)//left subtree is heavier before insertion, thus after that it is even unbalancedUpdateLeft(cur, revise_bfactor);else if(cur->factor==AVLB) {//after insertion, balance was destroiedcur->factor=AVLL;revise_bfactor=true;}else {cur->factor=AVLB;revise_bfactor=false;}}else revise_bfactor=false;}else {//insert to the right subtreepar=cur;AVLinsert(cur->right, newnode, par, sub_rebfactor);if(sub_rebfactor) {if(cur->factor==AVLL) {cur->factor=AVLB;revise_bfactor=false;}else if(cur->factor==AVLB) {cur->factor=AVLR;revise_bfactor=true;}else UpdateRight(cur, revise_bfactor);}else revise_bfactor=false;}return cur;}void Rebalance(AVLNode<T> *parofdel) {AVLNode<T> *cur;bool revise_bfactor=true;while( revise_bfactor && parofdel!= NULL ) {cur=parofdel;parofdel=parofdel->parent;int lrflag=0;if(parofdel!=NULL) {if(parofdel->left==cur) lrflag=-1;else lrflag=1;}switch(cur->factor) {case 0:if(parofdel!=NULL) {if(cur==parofdel->left) ++parofdel->factor;else --parofdel->factor;}break;case -1:case 1:revise_bfactor=false;break;case -2: //left sub tree is heavier, right rotationif(cur->left->factor==AVLB) {SingleRotateRight(cur);revise_bfactor=false;break;}else if(cur->left->factor==AVLL) SingleRotateRight(cur);else DoubleRotateRight(cur);switch(lrflag){case -1:parofdel->left=cur;++parofdel->factor;break;case 1:parofdel->right=cur;--parofdel->factor;break;case 0:root=cur;break;default:break;}break;case 2://right sub tree is heavier, left rotationif(cur->right->factor==AVLB) {SingleRotateLeft(cur);revise_bfactor=false;break;}else if(cur->right->factor==AVLR) SingleRotateLeft(cur);else DoubleRotateLeft(cur);switch(lrflag){case -1:parofdel->left=cur;++parofdel->factor;break;case 1:parofdel->right=cur;--parofdel->factor;break;case 0:root=cur;break;default:break;}break;default:cerr<<"error in rebalancing after deletion"<<endl;exit(0);break;}}}public://for the iteratortypedef T value_type;typedef value_type* pointer;typedef AVLTree_iterator<T, T&, T*> iterator;typedef AVLTree_const_iterator<T, T&, T*> const_interator;AVLTree(void) {root=NULL;size=0;}AVLTree(T *first, T *last) {root=NULL;size=0;T *cur=first;while(cur!=last) {insert(*cur);++cur;}}AVLTree(const AVLTree<T> &rhs) {root=copy( rhs.Root() );size=rhs.Size();}AVLTree<T> &operator=(const AVLTree<T> &rhs) {if(root==rhs) return this;DelTree(root);root=copy(rhs.Root());size=rhs.Size();return this;}~AVLTree(void) { DelTree(root); }iterator begin() {//return the iterator of the node which should be firstly calls forAVLNode<T> *cur=root;if(cur!=NULL) {while(cur->left!=NULL) cur=cur->left;}return AVLTree::iterator(cur, this);}iterator end() {//return the last node in the treereturn AVLTree::iterator(NULL, this);}iterator find(const T& item) {//find element in the treeAVLNode<T> *obj=findNode(item);if(obj!=NULL) return iterator(obj, this);else return this->end();}iterator insert(const T& item)  {//insert element in the treeAVLNode<T> *cur=root, *par=root, *newnode=NULL;bool revise_bfactor=false;newnode=GetNode(item, NULL, NULL, NULL);AVLinsert(cur, newnode, par, revise_bfactor);root=cur;//return newnode++size;return iterator(newnode, this);}bool erase(const T& item) {//if item exist, erase it and return trueiterator pos=find(item);if(pos!=end()) erase(pos);return pos!= end();}void erase(iterator pos) {AVLNode<T> *del=pos.pn;if(del==NULL) return;AVLNode<T> *parofdel=del->parent, *rcofdel, *lcofdel;//pointers for the deleted oneAVLNode<T> *prep=NULL, *parofrep=NULL;//pointers for the replacement oneiterator rep=pos;//erase del node and relink the tree nodesif(del->left==NULL) {rcofdel=del->right;if(parofdel==NULL) root=rcofdel; else if(parofdel->left==del) {parofdel->left=rcofdel;if(rcofdel!=NULL) rcofdel->parent=parofdel;++parofdel->factor;//left subtree shrinked}else {parofdel->right=rcofdel;if(rcofdel!=NULL) rcofdel->parent=parofdel;--parofdel->factor;//right subtree shrinked}}else if( del->right==NULL ) {lcofdel=del->left;if(parofdel==NULL) root=lcofdel; else if(parofdel->left==del) {parofdel->left=lcofdel;if(lcofdel!=NULL) lcofdel->parent=parofdel;++parofdel->factor;//left subtree shrinked}else {parofdel->right=lcofdel;if(lcofdel!=NULL) lcofdel->parent=parofdel;--parofdel->factor;//right subtree shrinked}}else {--rep;prep=rep.pn;    //inorder predecessorif(prep==del->left) {parofrep=parofdel;parofdel=prep;prep->parent=del->parent;prep->right=del->right;del->right->parent=prep;prep->factor=del->factor;++parofdel->factor;}else {parofrep=parofdel;parofdel=prep->parent;lcofdel=prep->left;    //right subtree must be NULL//replace the del with prepprep->parent=del->parent;prep->right=del->right;del->right->parent=prep;prep->left=del->left;del->left->parent=prep;prep->factor=del->factor;parofdel->right=lcofdel;if(lcofdel!=NULL) lcofdel->parent=parofdel;--parofdel->factor;}if(parofrep==NULL) root=prep;else if(parofrep->left==del) parofrep->left=prep;else parofrep->right=prep;}delete del;--size;//rebalance the tree from the parent (parofdel) of the deleted nodeRebalance(parofdel);}//virtual void erase(iterator first, iterator last);void LevelorderPrint() {queue< AVLNode<T> > parQ;queue< AVLNode<T> > chdQ;AVLNode<T> *cur=new AVLNode<T>;parQ.push(*root);while(!parQ.empty()) {do{*cur=parQ.front();parQ.pop();cout<<cur->data<<ends;if(cur->left!=NULL)chdQ.push(*(cur->left) );if(cur->right!=NULL) chdQ.push(*(cur->right) );}while(!parQ.empty());cout<<endl;parQ=chdQ;queue< AVLNode<T> > empty;swap(chdQ, empty);}delete cur;cur=NULL;}AVLNode<T> *Root() { return root; }int height(AVLNode<T> *cur) const {int r_depth, l_depth, depth;if(cur==NULL) depth=-1;else {r_depth=height(cur->right);l_depth=height(cur->left);depth=1+(r_depth>l_depth?r_depth:l_depth);}return depth;}bool empty() const {return root==NULL;}int Size() { return size; }};template<class T, class Ref, class Ptr>class AVLTree_iterator  {//iterator declarationfriend class AVLTree<T>;public:typedef AVLTree_iterator<T, T&, T*> iterator;typedef AVLTree_iterator<T, Ref, Ptr> self;typedef bidirectional_iterator_tag iterator_category; typedef T value_type;typedef Ptr pointer;typedef Ref reference;typedef ptrdiff_t difference_type;public:AVLTree_iterator() {pn=NULL;tree=NULL;}AVLTree_iterator(const AVLTree_iterator &rhs) {pn=rhs.pn;tree=rhs.tree;}bool operator==(const iterator &rhs) const {return pn == rhs.pn;}bool operator!=(const iterator &rhs) const {return pn != rhs.pn;}reference &operator*() const {if(pn==NULL) { cerr<<"AVLTree iterator operator*(): NULL reference"<<endl; exit(0); }return pn->data;}pointer operator->() const { return &( operator*() ); }self &operator++() {AVLNode<T> *p;if(pn==NULL) {//pn point to the end, next should be the first one in the treepn=tree->root;if(pn==NULL) { cerr<<"try to move on a empty tree!"<<endl; exit(0);}/*throw referenceError("allocate storage for new node failed!");*/while(pn->left!=NULL) pn=pn->left;}else if(pn->right != NULL) {//return the last node of the right subtreepn=pn->right;while(pn->left!=NULL) pn=pn->left;}else {//left subtree have been traversed and no right subtree, move to the parentp=pn->parent;while(p!=NULL && pn==p->right) {pn=p;p=p->parent;}pn=p;}return *this;//prefix, return current iterator (++iter)}self operator++(int) {self temp(pn, tree);++(*this);//invoke ++iter;return temp;//return a object but the reference}self &operator--() {AVLNode <T> *p;if(pn==NULL) {pn=tree->root;if(pn==NULL) {cerr<<"move on a empty tree!"<<endl; exit(0);}while(pn->right!=NULL) pn=pn->right;}else if(pn->left!=NULL) {pn=pn->left;while(pn->right!=NULL) pn=pn->right;}else {p=pn->parent;while(p!=NULL && pn==p->left) {pn=p;p=pn->parent;}pn=p;}return *this;}self operator--(int) {self temp(pn, tree);--*this;return temp;} private:AVLNode<T> *pn;AVLTree<T> *tree;AVLTree_iterator(AVLNode<T> *p, AVLTree<T> *t):pn(p), tree(t) {}};template<class T, class Ref, class Ptr>class AVLTree_const_iterator{friend class AVLTree<T>;public:typedef AVLTree_const_iterator<T, T&, T*> const_iterator;typedef AVLTree_const_iterator<T, Ref, Ptr> self;typedef bidirectional_iterator_tag iterator_category; typedef T value_type;typedef Ptr pointer;typedef Ref reference;public:AVLTree_const_iterator(){pn=NULL;tree=NULL;}AVLTree_const_iterator(const AVLTree_const_iterator &rhs){//copy constructionpn=rhs.pn;tree=rhs.tree;}AVLTree_const_iterator(const AVLTree_iterator &rhs){//copy constructionpn=rhs.pn;tree=rhs.tree;}bool operator==(const const_iterator &rhs) const {return pn == rhs.pn;}bool operator!=(const const_iterator &rhs) const {return pn != rhs.pn;}const reference &operator*() const {if(pn==NULL) { cerr<<"AVLTree const_iterator operator*(): NULL reference"<<endl; exit(0); }/*throw referenceError ("AVLTree const_iterator operator*(): NULL reference");*/return pn->data;}const pointer operator->() const { return &( operator*() ); }self &operator++() const { //move to the next node following inorder traversalAVLNode<T> *p;if(pn==NULL) {//pn point to the end, next should be the first one in the treepn=tree->root;if(pn==NULL) { cerr<<"try to move on a empty tree!"<<endl; exit(0);}/*throw referenceError("allocate storage for new node failed!");*/while(pn->left!=NULL) pn=pn->left;}else if(pn->right != NULL) {//return the last node of the right subtreepn=pn->right;while(pn->left!=NULL) pn=pn->left;}else {//left subtree have been traversed and no right subtree, move to the parentp=pn->parent;while(p!=NULL && pn==p->right) {pn=p;p=p->parent;}pn=p;}return *this;//prefix, return current iterator (++iter)}self operator++(int) const {//suffix iter++self temp(pn, tree);++(*this);//invoke ++iter;return temp;//return a object but the reference}self &operator--() const { //move to the previous node following inorder traversalAVLNode <T> *p;if(pn==NULL) {pn=tree->root;if(pn==NULL) {cerr<<"move on a empty tree!"<<endl; exit(0);}while(pn->right!=NULL) pn=pn->right;}else if(pn->left!=NULL) {pn=pn->left;while(pn->right!=NULL) pn=pn->right;}else {p=pn->parent;while(p!=NULL && pn==p->left) {pn=p;p=pn->parent;}pn=p;}return *this;}const_iterator operator--(int) const {self temp(pn, tree);--(*this);//invoke --iter;return temp;//return a object but the reference}private:const AVLNode<T> *pn;const AVLTree<T> *tree;AVLTree_const_iterator(const AVLNode<T> *p, const AVLTree<T> *t):pn(p), tree(t) {}};

原创粉丝点击