平衡二叉搜索树
任何结点的左子树和右子树高度最多相差1的二叉搜索树。
(1)AVL树的插入算法
a. 插入结点之后仍然是AVL树,则不调整;
b. 插入结点之后不再满足AVL树条件,则进行调整,根据导致不平衡的原因,分为:
a) LL型――单旋转调整
b) LR型――双旋转调整
c) RL型――双旋转调整
d) RR型――单旋转调整
下图是顺序插入单词{cup,cop,copy,hit,hi,his,hia}后得到的AVL树,单词之间按照字典顺序比较:
(2)AVL树的删除算法
a. 删除过程如BST结点的删除算法
b. 删除后调整――从被删除的结点找到祖父结点,然后开始单旋转或多旋转操作,一次旋转结束并不 意味着树已经平衡,因为这可能会导致它的祖先结点发生新的不平衡。所以这样的调整操作要一直进行下去,直到树平衡为止。
类的实现如下
//平衡二叉搜索树类定义与实现
template<class T> class BSTree;
//平衡二叉搜索树的结点类型定义
template<class T> struct TNode
{private:
TNode<T> *left;//左子树指针
TNode<T> *right;//右子树指针
public:
int balance;//平衡因子
T data;//数据域
friend class BSTree<T>;
//构造函数
TNode():left(NULL),right(NULL),balance(0){ }
TNode(T item,TNode<T> *left1,TNode<T> *right1)
:balance(0),data(item),left(left1),right(right1){ }
};
template<class T> class BSTree
{private:
int size;
public:
//构造函数
BSTree(TNode<T> *&root):size(0){root=NULL;}
//被ClearBST()所调用的函数
void DeleteTree(TNode<T> *&root);
//LL型调整操作
void LL(TNode<T> **a,TNode<T> **b);
//RR型调整操作
void RR(TNode<T> **a,TNode<T> **b);
//LR型调整操作
void LR(TNode<T> **a,TNode<T> **b);
//RL型调整操作
void RL(TNode<T> **a,TNode<T> **b);
//释放空间
void FreeBST(TNode<T> *&root);
//求平衡二叉搜索树中所有结点数
int BSTSize();
//判断平衡二叉搜索树是否为空
int BSTEmpty(TNode<T> *&root);
//取根指针
TNode<T> *GetRoot(TNode<T> *&root);
//从平衡二叉搜索树中查找元素
TNode<T> *BSTLocate(TNode<T> *&root,T item);
//向平衡二叉搜索树中插入元素
void BSTInsert(TNode<T> *&root,T item);
//中序遍历平衡二叉搜索树中的所有结点
void Inorder(TNode<T> *&root);
//求平衡二叉搜索树的深度
int BSTreeDepth(TNode<T> *&root);
//求平衡二叉搜索树中所有结点数
int BSTreeCount(TNode<T> *&root);
//求平衡二叉搜索树中所有叶子结点数
int BSTreeLeafCount(TNode<T> *&root);
//清除平衡二叉搜索树,使之变为一棵空树
void ClearBST(TNode<T> *&root);
//初始化平衡二叉搜索树
void SetTNode(TNode<T> *&root,T item);
//获取设置的平衡二叉搜索树的一个结点
TNode<T> *GetTNode(T item,TNode<T> *left,TNode<T> *right);
};
//平衡二叉搜索树的类实现
template<class T>
void BSTree<T>::DeleteTree(TNode<T> *&root)
{if(root==NULL) return;
if(root->left!=NULL)
DeleteTree(root->left);
if(root->right!=NULL)
DeleteTree(root->right);
free(root);
}
template<class T>
void BSTree<T>::LL(TNode<T> **a,TNode<T> **b)
{(*a)->balance=0;
(*a)->left=(*b)->right;
(*b)->balance=0;
(*b)->right=(*a);
}
template<class T>
void BSTree<T>::RR(TNode<T> **a,TNode<T> **b)
{(*a)->balance=0;
(*a)->right=(*b)->left;
(*b)->balance=0;
(*b)->left=(*a);
}
template<class T>
void BSTree<T>::LR(TNode<T> **a,TNode<T> **b)
{TNode<T> *c;
c=(*b)->right;//c是插入结点
(*a)->left=c->right;
(*b)->right=c->left;
c->left=(*b);
c->right=(*a);
switch(c->balance)
{case 0:(*a)->balance=0;
(*b)->balance=0;
break;
case 1:(*a)->balance=-1;//插入的结点在c的左子树
(*b)->balance=0;
break;
case -1:(*a)->balance=0;//插入的结点在c的右子树
(*b)->balance=1;
break;}
c->balance=0;
(*b)=c;//使b指向调整后的子树的根
}
template<class T>
void BSTree<T>::RL(TNode<T> **a,TNode<T> **b)
{TNode<T> *c;
c=(*b)->left; //c是插入结点
(*a)->right=c->left;
(*b)->left=c->right;
c->right=(*b);
c->left=(*a);
switch(c->balance)
{case 0:(*a)->balance=0;
(*b)->balance=0;
break;
case 1:(*a)->balance=0;//插入的结点在c的左子树
(*b)->balance=-1;
break;
case -1:(*a)->balance=1;//插入的结点在c的右子树
(*b)->balance=0;
break;}
c->balance=0;
(*b)=c;//使b指向调整后的子树的根
}
template<class T>
void BSTree<T>::FreeBST(TNode<T> *&root)
{DeleteTree(root);}
template<class T>
int BSTree<T>::BSTSize()
{return(size);}
template<class T>
int BSTree<T>::BSTEmpty(TNode<T> *&root)
{if(root==NULL) return(1);
else return(0);}
template<class T>
TNode<T> *BSTree<T>::GetRoot(TNode<T> *&root)
{return(root);}
template<class T>
TNode<T> *BSTree<T>::BSTLocate(TNode<T> *&root,T item)
{TNode<T> *t;
t=root;
while(t!=NULL)
{if(item==t->data) break;
else
if(item<t->data) t=t->left;
else t=t->right;}
return(t);
}
template<class T>
void BSTree<T>::BSTInsert(TNode<T> *&root,T item)
{TNode<T> *t,*p,*newN,*a,*b,*f;
newN=new TNode<T>;
newN->data=item;
if(root==NULL)
{root=newN;
size++;
return;}
t=root;p=NULL;
a=t;f=p;
while(t!=NULL)
{if(t->balance!=0)
{a=t;f=p;}
p=t;
if(item<t->data) t=t->left;
else t=t->right;}
if(item<p->data) p->left=newN;
else p->right=newN;
size++;
if(item<a->data)
{b=t=a->left;}
else {b=t=a->right;}
while(t!=NULL&&t->data!=item)
{if(item<t->data)
{t->balance=1;
t=t->left;}
else {t->balance=-1;t=t->right;}}
if(a->balance==0)
{if(item<a->data) a->balance=1;
else a->balance=-1;
return;}
else
if(item<a->data&&a->balance==-1||
item>a->data&&a->balance==1)
{a->balance=0;return;}
else
{if(a->balance==1)
if(b->balance==1)
LL(&a,&b);
else LR(&a,&b);
else
if(b->balance==-1) RR(&a,&b);
else RL(&a,&b);}
if(f==NULL) root=b;
else
{if(f->left==a) f->left=b;
else f->right=b;}
}
template<class T>
void BSTree<T>::Inorder(TNode<T> *&root)
{if(root!=NULL) {
Inorder(root->left);
cout<<setw(2)<<root->data;
Inorder(root->right);}
}
template<class T>
int BSTree<T>::BSTreeDepth(TNode<T> *&root)
{if(root==NULL) return 0;
else
{ //计算左子树的深度
int dep1=BSTreeDepth(root->left);
//计算右子树的深度
int dep2=BSTreeDepth(root->right);
//返回树的深度
if(dep1>dep2) return dep1+1;
else return dep2+1;}
}
template<class T>
int BSTree<T>::BSTreeCount(TNode<T> *&root)
{if(root==NULL) return 0;
else
return BSTreeCount(root->left)+BSTreeCount(root->right)+1;
}
template<class T>
int BSTree<T>::BSTreeLeafCount(TNode<T> *&root)
{if(root==NULL) return 0;
else
if(root->left==NULL && root->right==NULL) return 1;
else
return BSTreeLeafCount(root->left)+BSTreeLeafCount(root->right);
}
template<class T>
void BSTree<T>::ClearBST(TNode<T> *&root)
{DeleteTree(root);
root=NULL;
size=0;
}
template<class T>
void BSTree<T>::SetTNode(TNode<T> *&root,T item)
{root->data=item;
root->balance=0;
root->left=NULL;
root->right=NULL;
}
template<class T>
TNode<T>* BSTree<T>::GetTNode(T item,TNode<T> *left,TNode<T> *right)
{TNode<T> *ptr;
ptr=new TNode<T>;
ptr->data=item;
ptr->balance=0;
ptr->left=left;
ptr->right=right;
return(ptr);
}
调用如下
#include<conio.h>
#include<stdlib.h>
#include "AVLTREE.h"
using namespace std;
TNode<char> *q;
void main()
{cout<<"运行结果:\n";
int i;
char test[50]="abxyMNcdefgqwertyuizxcvbnm";
BSTree<char> t(q);
//cout<<"input data:\n";
//gets(test);
for(i=0;test[i]!='\0';i++)
t.BSTInsert(q,test[i]);
cout<<"平衡二叉搜索树的结点数="<<t.BSTSize()<<endl;
cout<<"平衡二叉搜索树的结点数="<<t.BSTreeCount(q)<<endl;
cout<<"平衡二叉搜索树的深度="<<t.BSTreeDepth(q)<<endl;
cout<<"平衡二叉搜索树的叶子结点数="<<t.BSTreeLeafCount(q)<<endl;
cout<<"中序遍历平衡二叉搜索树:\n";
t.Inorder(q);
getch();
t.FreeBST(q);
}