C++ AVL平衡树 模板

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

源代码如下:

#pragma once
//#include "STree.h"

template  class AVLTree;
template class AVLTree_iterator;
template class AVLTree_const_iterator;
template 
class AVLNode {
	friend class AVLTree;
	friend class AVLTree_iterator;
	friend class AVLTree_const_iterator;
protected:
	T data;
	AVLNode *left, *right, *parent;	
	int factor;//factor=height(right subtree)-height(left subtree)
	void copy(const AVLNode &rhs) {
		//if(rhs==NULL) {cout<<"error: no source"< *lptr=NULL, AVLNode *rptr=NULL, AVLNode *pptr=NULL, int ftor=0 )
		:data(item), left(lptr), right(rptr), parent(pptr), factor(ftor) {}	
	~AVLNode() {}
	AVLNode(const AVLNode &rhs) { copy(rhs);	}
	AVLNode &operator=(const AVLNode &rhs) { copy(rhs); return *this; }	
	int Factor() { return factor; }
};

template 
class AVLTree {
	enum {AVLL=-1, AVLB=0, AVLR=1 };// Balance state information stored in each node in AVL tree. 
	friend class AVLTree_iterator;
	friend class AVLTree_const_iterator;
protected:
	AVLNode *root;
	int size;
	AVLNode *GetNode(const T &item, AVLNode *lptr, AVLNode *rptr, AVLNode *pptr, int ftor=0) {
		AVLNode *newnode=new AVLNode(item, lptr, rptr, pptr, ftor);
		if( newnode==NULL ) {cerr<<"allocate storage for new node failed!"< *copy(AVLNode *rhs) {
		AVLNode *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 *_root) {
		if(_root==NULL) return;
		DelTree(_root->left);
		DelTree(_root->right);
		delete _root;
	}
	AVLNode *findNode(const T& item) const {//only the type of its return value is different  
													//with its base class, polymorphism can not be realized
		AVLNode *cur=root;
		while(cur!=NULL) {
			if(cur->data==item) return cur;
			else if(cur->dataright;
			else cur=cur->left;
		}
		return cur;
	}

	void SingleRotateRight(AVLNode * &cur) {
		AVLNode *leftchild=cur->left;
		AVLNode *par=cur->parent;
		//after the adjustment, all the nodes will be balanced
		leftchild->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 parent
		if(cur->left!=NULL) cur->left->parent=cur;

		leftchild->right=cur;		//the new right subtree of the new root should be its original parent		
		cur->parent=leftchild;

		leftchild->parent=par;
		cur=leftchild;              //leftchild now is the new root			
	}
	void DoubleRotateRight(AVLNode * &cur) {
		AVLNode *leftchild=cur->left;
		AVLNode *lc_rht_chd=leftchild->right;
		AVLNode *par=cur->parent;
		//after the adjustment, the balance factor should like this
		if(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;
		//rotation
		leftchild->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 * &cur) {
		AVLNode *rightchild=cur->right;
		AVLNode *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 * &cur) {
		AVLNode *rightchild=cur->right;
		AVLNode *rc_left_chd=rightchild->left;
		AVLNode *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 * &cur, bool &revise_bfactor) {
		AVLNode *leftchild=cur->left;
		if(leftchild->factor==AVLL) {//left subtree is heavier
			SingleRotateRight(cur);
			revise_bfactor=false;
		}
		else if(leftchild->factor==AVLR) {
			DoubleRotateRight(cur);
			revise_bfactor=false;
		}
		else {//error message
		}
	}
	void UpdateRight(AVLNode * &cur, bool &revise_bfactor) {
		AVLNode *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 *AVLinsert(AVLNode * &cur, AVLNode *newnode, AVLNode *par, bool &revise_bfactor){
		bool sub_rebfactor=false;   //denotes if the balance of the subtree was destroied
		if(cur==NULL) {   //a empty subtree is encountered, insert the newnode
			cur=newnode;
			cur->parent=par;
			cur->factor=AVLB;
			revise_bfactor=true;
		}
		else if(newnode->data < cur->data) {//insert to the left subtree
			par=cur;
			AVLinsert(cur->left, newnode, par, sub_rebfactor);
			if(sub_rebfactor) {//the balance of the left subtree is changed
				if(cur->factor==AVLL)//left subtree is heavier before insertion, thus after that it is even unbalanced
					UpdateLeft(cur, revise_bfactor);
				else if(cur->factor==AVLB) {//after insertion, balance was destroied
					cur->factor=AVLL;
					revise_bfactor=true;
				}
				else {
					cur->factor=AVLB;
					revise_bfactor=false;
				}
			}
			else revise_bfactor=false;
		}
		else {//insert to the right subtree
			par=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 *parofdel) {
		AVLNode *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 rotation
				if(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 rotation
				if(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"< iterator;
	typedef AVLTree_const_iterator 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 &rhs) {
		root=copy( rhs.Root() );
		size=rhs.Size();
	}
	AVLTree &operator=(const AVLTree &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 for
		AVLNode *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 tree
		return AVLTree::iterator(NULL, this);
	}

	iterator find(const T& item) {//find element in the tree
		AVLNode *obj=findNode(item);
		if(obj!=NULL) return iterator(obj, this);
		else return this->end();
	}
	iterator insert(const T& item)  {//insert element in the tree
		AVLNode *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 true
		iterator pos=find(item);
		if(pos!=end()) erase(pos);
		return pos!= end();
	}
	void erase(iterator pos) {
		AVLNode *del=pos.pn;			
		if(del==NULL) return;
		AVLNode *parofdel=del->parent, *rcofdel, *lcofdel;//pointers for the deleted one
		AVLNode *prep=NULL, *parofrep=NULL;//pointers for the replacement one
		iterator rep=pos;
		//erase del node and relink the tree nodes
		if(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 predecessor
			if(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 prep
				prep->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 node			
		Rebalance(parofdel);		
	}
	//virtual void erase(iterator first, iterator last);	

	void LevelorderPrint() {
	queue< AVLNode > parQ;
	queue< AVLNode > chdQ;
	AVLNode *cur=new AVLNode;
	parQ.push(*root);
	while(!parQ.empty()) {
		do{
			*cur=parQ.front();
			parQ.pop();
			cout<data<left!=NULL)	chdQ.push(*(cur->left) );
			if(cur->right!=NULL) chdQ.push(*(cur->right) );
		}	while(!parQ.empty());
		cout< > empty;
		swap(chdQ, empty);
	}
	delete cur;
	cur=NULL;
}
	AVLNode *Root() { return root; }
	int height(AVLNode *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 AVLTree_iterator  {//iterator declaration
		friend class AVLTree;
	public:
		typedef AVLTree_iterator iterator;
		typedef AVLTree_iterator 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"<data;
		}
		pointer operator->() const { return &( operator*() ); }

		self &operator++() {
			AVLNode *p;
			if(pn==NULL) {//pn point to the end, next should be the first one in the tree
				pn=tree->root;
				if(pn==NULL) { cerr<<"try to move on a empty tree!"<left!=NULL) pn=pn->left;
			}
			else if(pn->right != NULL) {//return the last node of the right subtree
				pn=pn->right;
				while(pn->left!=NULL) pn=pn->left;
			}
			else {//left subtree have been traversed and no right subtree, move to the parent
				p=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  *p;
			if(pn==NULL) {
				pn=tree->root;
				if(pn==NULL) {cerr<<"move on a empty tree!"<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 *pn;
		AVLTree *tree;
		AVLTree_iterator(AVLNode *p, AVLTree *t):pn(p), tree(t) {}
};
template
class AVLTree_const_iterator{
		friend class AVLTree;
	public:
		typedef AVLTree_const_iterator const_iterator;
		typedef AVLTree_const_iterator 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 construction
			pn=rhs.pn;
			tree=rhs.tree;
		}
		AVLTree_const_iterator(const AVLTree_iterator &rhs){//copy construction
			pn=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"<data;
		}
		const pointer operator->() const { return &( operator*() ); }

		self &operator++() const { //move to the next node following inorder traversal
			AVLNode *p;
			if(pn==NULL) {//pn point to the end, next should be the first one in the tree
				pn=tree->root;
				if(pn==NULL) { cerr<<"try to move on a empty tree!"<left!=NULL) pn=pn->left;
			}
			else if(pn->right != NULL) {//return the last node of the right subtree
				pn=pn->right;
				while(pn->left!=NULL) pn=pn->left;
			}
			else {//left subtree have been traversed and no right subtree, move to the parent
				p=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 traversal
			AVLNode  *p;
			if(pn==NULL) {
				pn=tree->root;
				if(pn==NULL) {cerr<<"move on a empty tree!"<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 *pn;
		const AVLTree *tree;
		AVLTree_const_iterator(const AVLNode *p, const AVLTree *t):pn(p), tree(t) {}
	};

你可能感兴趣的:(C/C++编程,经典算法)