以下用大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. ADO.net 连接字符串中的 |DataDirectory| 是什么

    |DataDirectory| does not come from config settings; you're mixing up three different things: Configu ...

  2. css3 选择器(三)

    接css3选择器(一) 接css3 选择器(二) 这篇和前两篇内容相关性不大,主要是涉及到一些css3的状态选择器,所以标题从一开始. 一.[:enabled]选择器 一看这个属性就知道是专为表单元素 ...

  3. (转)浅析Java中的访问权限控制

    原文地址: http://www.cnblogs.com/dolphin0520/p/3734915.html 今天我们来一起了解一下Java语言中的访问权限控制.在讨论访问权限控制之前,先来讨论一下 ...

  4. python爬虫学习(1) —— 从urllib说起

    0. 前言 如果你从来没有接触过爬虫,刚开始的时候可能会有些许吃力 因为我不会从头到尾把所有知识点都说一遍,很多文章主要是记录我自己写的一些爬虫 所以建议先学习一下cuiqingcai大神的 Pyth ...

  5. C语言中结构体赋值问题的讨论

    今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...

  6. Oozie coordinator 作业自定义的配置的一些方法

    Oozie的coordinator有啥用? The Oozie Coordinator system allows the user to define and execute recurrent a ...

  7. 用于灰度变换的一些实用的M函数

    关于MATLAB中如何对错误处理进行编程,先介绍一些东西: 函数nargin可以检测输入到M函数的参数的数目: 函数nargout可以检测M函数的输出: 函数nargchk能够在M函数体中检测传递的参 ...

  8. 使用using释放资源

    using关键字 using 关键字可以用来导命名空间,与java中的import类似. 我使用using的地方 using(SqlConnection con=new SplConnection(c ...

  9. 系统修改利器XueTr

    Windows系统修改利器XueTr 周银辉 在Windows下如果遇到某些进程弄死结束不了,某些文件弄死删不掉,拷贝不出来 (可能是因为你没有管理员权限,可能是因为人家是病毒,可能是系统保护文件,可 ...

  10. Membership 重置密码

    public ActionResult ChongZhiMiMa()        {            Membership.GetUser("admin").UnlockU ...