以下用大O表示节点,ABC表示三个集合。

  仅分析左子树的情况,因为对称,右子树的情况一样。

  插入节点前

      O

     /     \

    O        A

     /    \

B       C

  插入节点后:

      O

     /     \

    O        A

     /    \

B       C

/

O

此时造成了最高节点的不平衡,说明了B+2 - A = 2;另外可以知道B = C,考虑B<C,那么在插入节点前最高点就已经不平衡了,考虑B > C,那么最高的左子树就已经不平衡了,而不应该考虑最高点。所以此时可以知道A = B = C。

  左子树单旋转之后:

      O

     /     \

    B        O

     /          /    \

O         C       A

  对于最高点来说,左子树深度为B+1,右子树深度为A+1,即B + 1。

  对比插入后的树,可以知道只有原最高节点的深度发生变化,所以只需更新该节点的深度。

另外一种情况:

插入后:

 

      O

     /     \

    O        A

     /    \

B       C

/

O

此时如果单旋转,结果为:

      O

     /     \

    B        O

                 /    \

C       A

/

O

明显这个情况并没有得到解决。

所以首先要单右旋转最高节点的左子树,结果为:

      O

     /     \

    C        A

     /    \

O       O

/

B

此时可以知道C集合的深度发生了变化,需要更新C的深度,而之前更新的是最高点的深度,所以在旋转时需要更新原最高点和现最高点的深度。

第二次左旋转原最高点,结果为

      C

     /     \

    O        O

     /         /    \

B        O       A

这里面的正确有一些缺陷,应该把ABC集合多展开几层,否则在双旋转时的证明有些怪异,反正就是这个思路,因为画图实在是太麻烦了。

最后是代码:

  

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef struct _node
{
int element;
int high;
struct _node *lefttree;
struct _node *righttree;
}node; int gethigh(node *t)
{
if(t == )
return -;
return t->high;
} node *singlerotatewithleft(node *t)
{
node *tmp = t->lefttree;
t->lefttree = tmp->righttree;
tmp->righttree = t; tmp->high = ((gethigh(tmp->lefttree) > gethigh(tmp->righttree))?gethigh(tmp->lefttree):gethigh(tmp->righttree)) + ;
t->high = ((gethigh(t->lefttree) > gethigh(t->righttree))?gethigh(t->lefttree):gethigh(t->righttree)) + ;
return tmp;
} node *singlerotatewithright(node *t)
{
node *tmp = t->righttree;
t->righttree = tmp->lefttree;
tmp->lefttree = t; tmp->high = ((gethigh(tmp->lefttree) > gethigh(tmp->righttree))?gethigh(tmp->lefttree):gethigh(tmp->righttree)) + ;
t->high = ((gethigh(t->lefttree) > gethigh(t->righttree))?gethigh(t->lefttree):gethigh(t->righttree)) + ;
return tmp;
} node *doubleroratewithleft(node *t)
{
t->lefttree = singlerotatewithright(t->lefttree);
return singlerotatewithleft(t);
} node *doubleroratewithright(node *t)
{
t->righttree = singlerotatewithleft(t->righttree);
return singlerotatewithright(t);
} node *insert(node *t,int element)
{
if (t == )
{
t = (node *)malloc(sizeof(node));
t->element = element;
t->lefttree = t->righttree = ;
}
else if(t->element > element){
t->lefttree = insert(t->lefttree,element);
if(gethigh(t->lefttree) - gethigh(t->righttree) == )
if(element < t->lefttree->element)
t= singlerotatewithleft(t);
else
t= doubleroratewithleft(t);
}
else if(t->element < element){
t->righttree = insert(t->righttree,element);
if(gethigh(t->righttree) - gethigh(t->lefttree) == )
if(element > t->righttree->element)
t= singlerotatewithright(t);
else
t= doubleroratewithright(t); }
t->high = ((gethigh(t->lefttree) > gethigh(t->righttree))?gethigh(t->lefttree):gethigh(t->righttree)) + ;
return t;
} node *find(node *t,int element)
{
if(t == )
return ;
else if(t->element > element)
return find(t->lefttree,element);
else if(t->element < element)
return find(t->righttree,element);
else
return t;
} node* findmin(node *t)
{
if(t == )
return ;
if(t->lefttree == )
return t;
else
return findmin(t->lefttree);
} node *delele(node *t,int element)
{
if(t == )
return ;
else if(t->element > element)
t->lefttree = delele(t->lefttree,element);
else if(t->element < element)
t->righttree = delele(t->righttree,element);
else
{
if(t->lefttree && t->righttree)
{
node *tmp;
tmp = findmin(t->righttree);
t->element = tmp->element;
t->righttree = delele(t->righttree,tmp->element);
}
else
{
node *tmp;
tmp = t->lefttree?t->lefttree:t->righttree;
free(t);
t = tmp;
}
}
return t;
} void printtree(node *t)
{
if(t == )
return;
printtree(t->lefttree);
printf("%d\t",t->element);
printf("high = %d\n",t->high);
printtree(t->righttree);
} int main()
{
int a[] = {,,,,,,,,};
node *t;
int i = ;
t = insert(,);
for(;i<;i++){
t = insert(t,a[i]);
//printtree(t);
//sleep(1);
}
//t = delele(t,6);
printtree(t);
printf("\n");
//while(1);
return ;
}

 

 

 

avl树的操作证明的更多相关文章

  1. AVL树插入操作实现

    为了提高二插排序树的性能,规定树中的每个节点的左子树和右子树高度差的绝对值不能大于1.为了满足上面的要求需要在插入完成后对树进行调整.下面介绍各个调整方式. 右单旋转 如下图所示,节点A的平衡因子(左 ...

  2. AVL树相关操作

    #include <iostream> using namespace std; //AVL树的节点 template<typename T> class TreeNode { ...

  3. 纸上谈兵:AVL树

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 二叉搜索树的深度与搜索效率 我们在树, 二叉树, 二叉搜索树中提到,一个有n个节点 ...

  4. 纸上谈兵: AVL树[转]

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 二叉搜索树的深度与搜索效率 我们在树, 二叉树, 二叉搜索树中提到,一个有n个节点 ...

  5. 树-二叉搜索树-AVL树

    树-二叉搜索树-AVL树 树 树的基本概念 节点的度:节点的儿子数 树的度:Max{节点的度} 节点的高度:节点到各叶节点的最大路径长度 树的高度:根节点的高度 节点的深度(层数):根节点到该节点的路 ...

  6. 图解数据结构树之AVL树

    AVL树(平衡二叉树): AVL树本质上是一颗二叉查找树,但是它又具有以下特点:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树.在AVL树中任何节点的两个子 ...

  7. 数据结构树之AVL树(平衡二叉树)

    一 什么是AVL树(平衡二叉树): AVL树本质上是一颗二叉查找树,但是它又具有以下特点:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树.在AVL树中任何节 ...

  8. AVL树Python实现

    # coding=utf-8 # AVL树Python实现 def get_height(node): return node.height if node else -1 def tree_mini ...

  9. AVL树(平衡二叉树)

    定义及性质 AVL树:AVL树是一颗自平衡的二叉搜索树. AVL树具有以下性质: 根的左右子树的高度只差的绝对值不能超过1 根的左右子树都是 平衡二叉树(AVL树) 百度百科: 平衡二叉搜索树(Sel ...

随机推荐

  1. 漫谈C++11 Thread库之原子操作

    我在之前一篇博文<漫谈C++11 Thread库之使写多线程程序>中,着重介绍了<thread>头文件中的std::thread类以及其上的一些基本操作,至此我们动手写多线程程 ...

  2. STL 堆

    洛谷P3378 [模板]堆 #include <iostream> #include <cstdio> #include <algorithm> #include ...

  3. POJ1961[KMP 失配函数]

    Period Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 16776   Accepted: 8077 Descripti ...

  4. 第7章 权限管理(3)_文件系统属性和sudo权限

    3. 文件系统属性chattr权限 (1)chattr命令 命令格式: #chattr [+-=][选项] 文件或目录名 +.-.= 分别表示增加权限.删除权限和赋于某种权限 选项 i:主要用来防止对 ...

  5. Eclipse使用svn文章列表

    http://www.cnblogs.com/duanxz/p/3334660.html http://www.cnblogs.com/duanxz/p/3334660.html http://130 ...

  6. iOS Webview 实现修改javascript confirm 和 alert

    贴代码: @interface UIWebView (JavaScriptAlert) -(void) webView:(UIWebView *)sender runJavaScriptAlertPa ...

  7. java多线程系类:JUC线程池:02之线程池原理(一)

    在上一章"Java多线程系列--"JUC线程池"01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我 ...

  8. node基础10:处理异常

    1.处理异常 当发生异常时,如果不作处理,那么服务器会奔溃.由于node的异步调用的特性,所以不但要考虑主程序的异常,还有处理异步调用的异常. 代码如下: /** * server.js */ var ...

  9. edge 浏览器中数字显示为链接

    在win10 中的Edge浏览器中部分格式的数字显示链接.经过各种搜索找到一篇文章 How to remove phone number link on Iphone? ,通过这篇文章了解 edge ...

  10. EasyUI datagrid : 启用行号、固定列及多级表头后,头部行号位置单元格错位的问题

    症状如图: 上图中,行号列与checkbox 列融合了.解决方法是在datagrid 的 onLoadSuccess 事件中加入如下代码: var opts = $(this).datagrid('o ...