在上篇博文中的二叉搜索树的基础上(无实际联系,只是当时开发的时候参考),实现了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->data- right;
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) {}
};