AVL树是一种自平衡的二叉树,在AVL树里任何节点的两个子树的高度之差不能超过1,所以他是一种高度平衡的二叉查找树,他能保证查找,插入,删除在最坏的情况下都是
O(log(n))的,不过插入和删除都需要通过一次或多次的单旋转或双旋转来调节平衡!
以下是调节平衡的例子:
接下来是我的C++代码实现:
#include<iostream>
#include<cstdio>
using namespace std;
#include<ctime>
template<class obj_s>
class avltree{
struct avlnode
{
obj_s ele;
avlnode *left;
avlnode *right;
int height;
avlnode(const obj_s &tele,avlnode *lt=NULL,avlnode *rt=NULL,int h=0)
:ele(tele),left(lt),right(rt),height(h){}
};
int height (avlnode *t)const
{
return t==NULL?-1:t->height;
}
avlnode *root;
void clear(avlnode * &t)
{
if(t==NULL)
return;
clear(t->left);
clear(t->right);
delete t;
}
avlnode * clone(avlnode * t)
{
if(t!=NULL)
return new avlnode(t->ele,clone(t->left),clone(t->right),t->height);
return NULL;
}
void insert(const obj_s &x,avlnode *&t)
{
if(t==NULL)
t=new avlnode(x);
else if(x<t->ele)
{ insert(x,t->left);
if(height(t->left)-height(t->right)==2)
{ if(x<t->left->ele)
rotatewithleftchild(t);
else
doublewithleftchild(t);
}
}
else if(t->ele<x)
{ insert(x,t->right);
if(height(t->left)-height(t->right)==-2)
{if(t->right->ele<x)
rotatewithrightchild(t);
else
doublewithrightchild(t);
}
}
else
;
t->height=height(t->left)-height(t->right)>0?height(t->left)+1:height(t->right)+1;
}
void remove(const obj_s &x,avlnode * &t)
{
if(t==NULL)
return ;
else if(x<t->ele)
{
remove(x,t->left);
if(height(t->right)-height(t->left)==2)
{
if(height(t->right->left)-height(t->right->right)<=0) //如果右左比右右小,那实行右单旋,否者右双旋,以下类似,
//思想就是删除与插入基本是相反的过程
rotatewithrightchild(t);
else
doublewithrightchild(t);
}
}
else if(x>t->ele)
{
remove(x,t->right);
if(height(t->left)-height(t->right)==2)
{
if(height(t->left->left)-height(t->left->right)>=0)
rotatewithleftchild(t);
else
doublewithleftchild(t);
}
}
else if(t->left !=NULL && t->right !=NULL)
{
t->ele=findMin(t->right)->ele;
remove(t->ele,t->right);
if(height(t->left)-height(t->right)==2)
{
if(height(t->left->left)-height(t->left->right)>=0)
rotatewithleftchild(t);
else
doublewithleftchild(t);
}
}
else
{
avlnode *oldnode=t;
t=(t->left!=NULL)?t->left:t->right;
delete oldnode;
}
if(t!=NULL)
t->height=height(t->left)-height(t->right)>0?height(t->left)+1:height(t->right)+1;
}
void rotatewithleftchild(avlnode *&t2)
{
avlnode *t1=t2->left;
t2->left=t1->right;
t1->right=t2;
t2->height=height(t2->left)-height(t2->right)>0?height(t2->left)+1:height(t2->right)+1;
t1->height=height(t1->left)-t2->height>0?height(t1->left)+1:t2->height+1;
t2=t1;
}
void rotatewithrightchild(avlnode *&t1)
{
avlnode *t2=t1->right;
t1->right=t2->left;
t2->left=t1;
t1->height=height(t1->left)-height(t1->right)>0?height(t1->left)+1:height(t1->right)+1;
t2->height=height(t2->right)-t1->height>0?height(t2->right)+1:t1->height+1;
t1=t2;
}
void doublewithleftchild(avlnode *&t)
{
rotatewithrightchild(t->left);
rotatewithleftchild(t);
}
void doublewithrightchild(avlnode *&t)
{
rotatewithleftchild(t->right);
rotatewithrightchild(t);
}
void display(avlnode *t,int i=0)
{
if(t!=NULL)
{
display(t->right,i+1);
for(int j=0;j<i;j++)
cout<<" ";
cout<<t->ele<<endl;
display(t->left,i+1);
}
}
avlnode *findMin(avlnode *t)const
{
if(t==NULL)
return NULL;
if(t->left==NULL)
return t;
return findMin(t->left);
}
avlnode *findMax(avlnode *t)const
{
if(t==NULL)
return NULL;
if(t->right==NULL)
return t;
return findMax(t->right);
}
bool contains(const obj_s &x,avlnode *t)const//查找;
{
if(t==NULL)
return false;
else if(x<t->ele)
return contains(x,t->left);
else if(x>t->ele)
return contains(x,t->right);
else
return true;
}
public:
avltree(){root=NULL;}
avltree(const avltree &rhs)
{ root=NULL;
*this=rhs;
}
~avltree(){clear();}
void clear()
{
clear(root);
root=NULL;
}
avltree & operator=(const avltree &rhs)
{ if(this!=&rhs)
{ clear();
root=clone(rhs.root);
}
return *this;
}
void insert (const obj_s &x)
{
insert(x,root);
}
int height()
{
return height(root);
}
void display()
{
display(root);
}
const obj_s & findMin()const
{
return findMin(root)->ele;
}
const obj_s & findMax()const
{
return findMax(root)->ele;
};
void remove(const obj_s &x)
{
remove(x,root);
}
bool contains(const obj_s &x)
{
return contains(x,root);
}
};
int main(){
freopen("out.txt","w",stdout);
avltree<int> T;
clock_t start,finish;
start=clock();
for(int i=1;i<=100;i++)
T.insert(i);
T.display();
finish=clock();
cout<<double(finish-start)/CLOCKS_PER_SEC<<"s"<<endl;
fclose(stdout);
return 0;
}
然后是out.txt的结果: 100
99
98
97
96
95
94
93
92
91
90
89
88
87
86
85
84
83
82
81
80
79
78
77
76
75
74
73
72
71
70
69
68
67
66
65
64
63
62
61
60
59
58
57
56
55
54
53
52
51
50
49
48
47
46
45
44
43
42
41
40
39
38
37
36
35
34
33
32
31
30
29
28
27
26
25
24
23
22
21
20
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0.000657s
可以看到,这棵树是非常平衡的,尽管我是按照顺序插入也是如此,这是普通的二叉查找树所无法实现的。