平衡因子:左子树和右子树高度差。用HB(k)表示。每一个节点都有这么一个平衡因子。
AVL中所有节点的HB(k)的绝对值不大于1
AVL树最少节点高度:
设AVL树高h,N(h)表示树高为h的AVL树的节点数。最少节点数出现在这种情况下:
左子树高为h-1,右子树高为h-2.<==>N(h)=N(h-1)+N(h-2)+1;<==>h=1.44logn
AVL树最多节点高度:
N(h)=2N(h-1)+1<==>h=logn
插入删除操作会使得AVL树的高度增加1或减少1.若AVL树的性质在节点X遭到破坏,则表明X的左子树与右子树的高度差为2.需要对节点X进行旋转操作。每次旋转操作能够使得X的高度减1。所以只需要对节点X进行旋转即可。
LL旋转:节点X的平衡因子为2的时候进行的操作。
将(X的左子树)的右子树作为X的左子树。将X作为(X的左子树)的右子树。
RR旋转:节点X的平衡因子为-2的时候进行的操作。
将(X的右子树)的左子树作为X的右子树。将X作为(X的右子树)的左子树。
LR旋转:节点X的左子树的右子树多了一个节点导致了不平衡。先对X的左子树进行RR旋转,问题变为了LL旋转的问题了。然后对X进行LL旋转
func.h
avl.h
main.cpp
AVL中所有节点的HB(k)的绝对值不大于1
AVL树最少节点高度:
设AVL树高h,N(h)表示树高为h的AVL树的节点数。最少节点数出现在这种情况下:
左子树高为h-1,右子树高为h-2.<==>N(h)=N(h-1)+N(h-2)+1;<==>h=1.44logn
AVL树最多节点高度:
N(h)=2N(h-1)+1<==>h=logn
插入删除操作会使得AVL树的高度增加1或减少1.若AVL树的性质在节点X遭到破坏,则表明X的左子树与右子树的高度差为2.需要对节点X进行旋转操作。每次旋转操作能够使得X的高度减1。所以只需要对节点X进行旋转即可。
LL旋转:节点X的平衡因子为2的时候进行的操作。
将(X的左子树)的右子树作为X的左子树。将X作为(X的左子树)的右子树。
RR旋转:节点X的平衡因子为-2的时候进行的操作。
将(X的右子树)的左子树作为X的右子树。将X作为(X的右子树)的左子树。
LR旋转:节点X的左子树的右子树多了一个节点导致了不平衡。先对X的左子树进行RR旋转,问题变为了LL旋转的问题了。然后对X进行LL旋转
RL旋转:节点X的右子树的左子树多了一个节点导致了不平衡。先对X的右子树进行LL旋转,问题变为了RR旋转的问题了。然后对X进行RR旋转。
func.cpp
#include <cstdio>
#include "avl.h"
inline int max(int x,int y){
if(x>y)return x;
return y;
}
int height(AVL* root){
if(!root)return -1;
return root->h;
}
/*AVL旋转操作*/
AVL* singleRotateLL(AVL* root){
AVL* left=root->left;
root->left=left->right;
left->right=root;
root->h=max(height(root->left),height(root->right))+1;
left->h=max(height(left->left),height(left->right))+1;
return left;
}
AVL* singleRotateRR(AVL* root){
AVL* right=root->right;
root->right=right->left;
right->left=root;
root->h=max(height(root->left),height(root->right))+1;
right->h=max(height(right->left),height(right->right))+1;
return right;
}
AVL* doubleRotateLR(AVL* root){
root->left=singleRotateRR(root->left);
return singleRotateLL(root);
}
AVL* doubleRotateRL(AVL* root){
root->right=singleRotateLL(root->right);
return singleRotateRR(root);
}
/*AVL插入节点*/
AVL* insert(AVL* root,AVL* parent,int val){
if(!root){
root=new AVL(val,0,NULL,NULL);
}
else if(val<root->val){
root->left=insert(root->left,root,val);
if(height(root->left)-height(root->right)==2){
if(val<root->left->val){
root=singleRotateLL(root);
}else{
root=doubleRotateLR(root);
}
}
}
else if(val>root->val){
root->right=insert(root->right,root,val);
if(height(root->right)-height(root->left)==2){
if(val>root->right->val){
root=singleRotateRR(root);
}else{
root=doubleRotateRL(root);
}
}
}
root->h=max(height(root->left),height(root->right))+1;
return root;
}
int find(AVL* root,int val){
if(!root)return -1;
if(root->val==val)return val;
if(val<root->val)return find(root->left,val);
return find(root->right,val);
}
AVL* findMin(AVL* root){
if(root==NULL)return NULL;
while(root->left){
root=root->left;
}
return root;
}
AVL* deleteAVL(AVL* root,int val){
if(!root)return NULL;
else if(val<root->val){
root->left=deleteAVL(root->left,val);
// printf("%d %d",height(root->right),height(root->left));
if(height(root->right)-height(root->left)==2){
if(height(root->right->left)>height(root->right->right)){
root=doubleRotateRL(root);
}else
root=singleRotateRR(root);
}
}
else if(val>root->val){
root->right=deleteAVL(root->right,val);
if(height(root->left)-height(root->right)==2){
if(height(root->left->left)>height(root->left->right)){
root=singleRotateLL(root);
}else
root=doubleRotateLR(root);
}
}
else if(root->left&&root->right){
AVL* tmp=findMin(root->right);
root->val=tmp->val;
root->right=deleteAVL(root->right,tmp->val);
}
else
{
AVL* tmp=root;
if(root->left){
root=root->left;
}else{
root=root->right;
}
delete tmp;
}
if(root!=NULL){
root->h=max(height(root->left),height(root->right))+1;
}
return root;
}
func.h
AVL* insert(AVL* root,AVL* parent,int val);
AVL* singleRotateRR(AVL* root);
AVL* singleRotateLL(AVL* root);
AVL* doubleRotateLR(AVL* root);
AVL* doubleRotateRL(AVL* root);
int find(AVL* root,int val);
AVL* deleteAVL(AVL* root,int val);
avl.h
class AVL{
public:
int val;
int h;
AVL* left;
AVL* right;
AVL(){}
AVL(int val,int h,AVL* left,AVL* right){
this->val=val;
this->h=h;
this->left=left;
this->right=right;
}
};
main.cpp
#include <cstdio>
#include <queue>
#include "avl.h"
#include "func.h"
using namespace std;
void show(AVL* root,AVL* base){
queue<AVL*> q;
q.push(root);
q.push(NULL);
while(!q.empty()){
AVL* root=q.front();
q.pop();
if(!root){
printf("\n");
if(q.empty())break;
q.push(NULL);
continue;
}
if(root->val==-1){
printf(" ");
continue;
}
printf("%d ",root->val);
if(root->left)q.push(root->left);
else q.push(base);
if(root->right)q.push(root->right);
else q.push(base);
}
}
int main(){
int n,x,m;
while(scanf("%d%d",&n,&m)!=EOF){
AVL *root=NULL,*base=new AVL(-1,0,NULL,NULL);
for(int i=0;i<n;i++){
scanf("%d",&x);
root=insert(root,NULL,x);
}
show(root,base);
for(int i=0;i<m;i++){
scanf("%d",&x);
int val=find(root,x);
printf("%d\n",val);
}
while(scanf("%d",&x)!=EOF){
root=deleteAVL(root,x);
show(root,base);
}
}
return 0;
}