[导入]C++实践笔记(四)----AVL树的简单实现

    关于AVL树的分析,请见:数据结构与算法分析学习笔记(二)--AVL树的算法思路整理

    这里给出AVL树的结构定义以及insert,remove和print三种操作的例程:

 

  1 #include <iostream>
  2 #include <list>
  3 #include <utility>
  4 #include <string>
  5 using namespace std;
  6 
  7 static const string PRINT_SPACES ="  ";
  8 
  9 template <typename Object>
 10 class AVLTree
 11 {
 12 public:
 13     AVLTree(){root=NULL;}
 14 
 15     void insert(const Object &x)
 16     {insert(x,root);}
 17     void remove(const Object &x)
 18     {remove(x,root);}
 19 
 20     void print();
 21 
 22 private:
 23     struct AVLnode
 24     {
 25         Object data;
 26         AVLnode *left;
 27         AVLnode *right;
 28         int height;
 29 
 30         AVLnode(Object ob,AVLnode *l,AVLnode *r,int h=0):data(ob),left(l),right(r),height(h){}
 31     };
 32 
 33     AVLnode *root;
 34 
 35     void insert(const Object &x,AVLnode * &t);
 36 
 37     void remove(const Object &x,AVLnode *&t);
 38 
 39     void leftSingleRotation(AVLnode * &t);
 40     void rightSingleRotation(AVLnode * &t);
 41 
 42     void leftDoubleRotation(AVLnode * &t);
 43     void rightDoubleRotation(AVLnode * &t);
 44 
 45     int height(AVLnode * &t)
 46     {
 47         //结点的高度,空结点的高度为-1
 48         return t==NULL?-1:t->height;
 49     }
 50 
 51     int max(int a,int b)
 52     {
 53         return a<b?b:a;
 54     }
 55 
 56     int powerOf2(int x)//求2的x次方(x大于等于0)
 57     {
 58         if(x==0)return 1;
 59         int m=1;
 60         while(--x>=0)
 61             m*=2;
 62         return m;    
 63     }
 64 
 65     AVLnode * max_node(AVLnode * t)//max和min使用递归的话不能使用引用形参,不能返回引用
 66     {
 67         if(!t)
 68             return NULL;
 69         if(t->right)
 70             return max_node(t->right);
 71         else
 72             return t;
 73     }
 74 
 75     AVLnode * min_node(AVLnode * t)
 76     {
 77         if(t)//考虑一下t为空的情况,使其更全面,毕竟这个函数是可以加一个public版本的重载供用户使用
 78             while(t->left)
 79                 t=t->left;
 80         return t;
 81     }
 82 };
 83 
 84 template <typename Object>
 85 void AVLTree<Object>::insert(const Object &x,AVLnode * &t)
 86 {
 87     if(!t)
 88         t=new AVLnode(x,NULL,NULL);
 89     else if(x<t->data)
 90     {
 91         insert(x,t->left);
 92         if(height(t->left)-height(t->right)==2)//在左子树插入结点后,不可能右子树比左子树高2
 93             if(x<t->left->data)
 94                 leftSingleRotation(t);//左单旋转
 95             else
 96                 leftDoubleRotation(t);//左双旋转
 97         else//不需要调整就满足平衡条件的话,只需要重新计算其高度就好
 98             t->height=max(height(t->left),height(t->right))+1;
 99     }
100     else if(x>t->data)
101     {
102         insert(x,t->right);
103         if(height(t->right)-height(t->left)==2)
104             if(x>t->right->data)
105                 rightSingleRotation(t);//右单旋转
106             else
107                 rightDoubleRotation(t);//右双旋转
108         else
109             t->height=max(height(t->left),height(t->right))+1;
110     }
111     else;//不考虑重复的值
112 }
113 
114 template <typename Object>
115 void AVLTree<Object>::leftSingleRotation(AVLnode * &t)//左单旋转
116 {
117     AVLnode *s=t->left;
118     t->left=s->right;
119     s->right=t;
120     t->height=max(height(t->left),height(t->right))+1;//重新计算s和t的高度
121     s->height=max(height(s->left),t->height)+1;
122     t=s;
123 }
124 
125 template <typename Object>
126 void AVLTree<Object>::rightSingleRotation(AVLnode * &t)
127 {
128     AVLnode *s=t->right;
129     t->right=s->left;
130     s->left=t;
131     t->height=max(height(t->left),height(t->right))+1;
132     s->height=max(t->height,height(s->right))+1;
133     t=s;
134 }
135 
136 template <typename Object>
137 void AVLTree<Object>::leftDoubleRotation(AVLnode * &t)//左双旋转
138 {
139     AVLnode *p=t->left;
140     AVLnode *q=p->right;
141     t->left=q->right;
142     p->right=q->left;
143     q->left=p;
144     q->right=t;
145     t->height=max(height(t->left),height(t->right))+1;//重新计算3个结点的高度
146     p->height=max(height(p->left),height(p->right))+1;
147     q->height=max(p->height,t->height)+1;
148     t=q;
149 }
150 
151 template <typename Object>
152 void AVLTree<Object>::rightDoubleRotation(AVLnode * &t)
153 {
154     AVLnode *p=t->right;
155     AVLnode *q=p->left;
156     t->right=q->left;
157     p->left=q->right;
158     q->right=p;
159     q->left=t;
160     t->height=max(height(t->left),height(t->right))+1;
161     p->height=max(height(p->left),height(p->right))+1;
162     q->height=max(t->height,p->height)+1;
163     t=q;
164 }
165 
166 template <typename Object>
167 void AVLTree<Object>::remove(const Object &x,AVLnode *&t)
168 {
169     if(!t)return;//没有找到要删除的值,do nothing
170     if(x<t->data)
171     {
172         remove(x,t->left);
173         if(height(t->right)-height(t->left)==2)
174         {
175             //右子树比左子树高2,那么在删除操作之前右子树比左子树高1,
176             //也就是说t的右子树必然不为空,甚至必然有非空子树(高度至少为1).
177             AVLnode *s=t->right;
178             if(height(s->left)>height(s->right))
179                 rightDoubleRotation(t);//右双旋转
180             else
181                 rightSingleRotation(t);//右单旋转
182         }
183         else
184             //不需要调整就满足平衡条件的话,只需要重新计算其高度就好
185             t->height=max(height(t->left),height(t->right))+1;
186     }
187     else if(x>t->data)
188     {
189         remove(x,t->right);
190         if(height(t->left)-height(t->right)==2)
191         {
192             AVLnode *s=t->left;
193             if(height(s->right)>height(s->left))
194                 leftDoubleRotation(t);//左双旋转
195             else
196                 leftSingleRotation(t);//左单旋转
197         }
198         else
199             t->height=max(height(t->left),height(t->right))+1;
200     }
201     else
202     {
203         if(t->left&&t->right)
204         //t的左右子树都非空,把remove操作转移到只有一个非空子树的结点或者叶子结点上去
205         {
206             if(height(t->left)>height(t->right))
207             //把remove操作往更高的那颗子树上转移
208             {
209                 //左子树中的最大值
210                 t->data=max_node(t->left)->data;
211                 remove(t->data,t->left);
212             }
213             else
214             {
215                 //右子树中的最小值
216                 t->data=min_node(t->right)->data;
217                 remove(t->data,t->right);
218             }
219         }
220         else
221         {
222             AVLnode *oldnode=t;
223             t=t->left?t->left:t->right;
224             delete oldnode;
225         }
226     }
227 }
228 
229 //使用队列层次遍历打印树
230 template <typename Object>
231 void AVLTree<Object>::print()
232 {
233     if(!root)return;
234     list<pair<AVLnode *,int> > lis;//int是标志位,0表示正常值,-1表示此处没有值,应打印空格
235     lis.push_back(make_pair(root,0));
236     AVLnode *em=new AVLnode(0,NULL,NULL);//一个空的点
237     int count=1,j=0;//count表示当前行的最大结点数,j表示当前行已打印的结点数(空结点也计数)
238     int hg=root->height;//当前行的高度,计算空格时使用
239 
240     while(hg>=0)//当hg<0时说明最后一行(树叶)已经打印完毕
241     {
242         while(j++!=count)
243         {
244             for(int i=1;i<powerOf2(hg);i++)
245                 cout<<PRINT_SPACES;//打印前一部分空格
246             if(lis.front().second==0)
247                 cout<<lis.front().first->data;
248             else
249                 cout<<PRINT_SPACES;//int位为-1,则打印空格以对齐
250             if(lis.front().first->left)//左子树入队
251                 lis.push_back(make_pair(lis.front().first->left,0));
252             else
253                 lis.push_back(make_pair(em,-1));
254             if(lis.front().first->right)//右子树入队
255                 lis.push_back(make_pair(lis.front().first->right,0));
256             else
257                 lis.push_back(make_pair(em,-1));
258             for(int i=0;i<powerOf2(hg);i++)
259                 cout<<PRINT_SPACES;//打印后一部分空格
260             lis.pop_front();
261         }
262         j=0;
263         count*=2;//下一行的最大节点数是上一行的两倍
264         --hg;//高度减1
265         cout<<endl;    //换行
266     }
267     delete em;
268     lis.clear();
269 }

 

作者: Barryhe 发表于 2011-11-28 16:30 原文链接

评论: 0 查看评论 发表评论


最新新闻:
· Google雅虎等呼吁欧盟勿制订过于严格隐私法律(2011-11-28 21:06)
· 强龙难压地头蛇 微软WP7俄罗斯忍痛割Bing(2011-11-28 20:27)
· 奇艺启动新域名背后:解决视听许可证遗留问题(2011-11-28 20:25)
· Kindle“黑色星期五”销量达去年同期四倍(2011-11-28 20:24)
· 维基解密本周将启动新在线系统(2011-11-28 20:21)

编辑推荐:如何快速成为Javascript高手的思考

网站导航:博客园首页  我的园子  新闻  闪存  博问  知识库


文章来源:http://www.cnblogs.com/heqile/archive/2011/11/28/2266385.html

posted on 2011-11-28 21:57 Barryhe 阅读(254) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2011年11月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

导航

统计

常用链接

留言簿

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜