AVL树的基本操作
来源:互联网 发布:30岁开始学编程 编辑:程序博客网 时间:2024/05/16 01:04
AvlTree的各种操作
AVL树是带有平衡条件的二叉查找树,要满足树中的每个节点的左子树和右子树的高度最多相差1。
- 插入操作
要使插入后生成的树为AVL树,就必须每插入一个节点,就判断一下左右子树的高度差是不是大于1,因此我们要记录每个节点的高度(这儿高的定义是一棵树ni的高是从ni到一片树叶的最长路径的长,空树的高度为-1树叶的高度为0)。
typedef struct AvlNode *AvlTree;struct AvlTree{ int x; AvlTree Left; AvlTree Right; int Height; //要记录高度};AvlTree Insert(int X,AvlTree T);
关键是插入后的判断,用T->Left->Height - T->Right->Height==2来判断左右子树的高度差是不对的,因为由于T的左右子树可能为NULL,因此要在用个计算节点高度的函数,对为NULL的情况讨论一下。
int Height(Position P){ if (P == NULL) { return -1; //这儿空树的高度为-1 }else { return P->Height; }}
AvlTree Insert(int X, AvlTree T){ if (T == NULL){ T = (AvlTree) malloc (sizeof(struct AvlNode)); T->x = X; T->Left = NULL; T->Right = NULL; T->Height = 0; }else if (T->x > X){ T->Left = Insert(X,T->Left); if ( Height(T->Left) - Height(T->Right) == 2){ if ( X < T->Left->x ){ T = SingleRotateWithLeft(T); }else{ T = DoubleRotateWithLeft(T); } } }else if ( T->x < X){ T->Right = Insert(X, T->Right); if ( Height(T->Right) - Height(T->Left) == 2 ){ if (X > T->Right->x){ T = SingleRotateWithRight(T); }else{ T = DoubleRotateWithRight(T); } } } T->Height = Max(Height(T->Left),Height(T->Right))+1; return T; //不要忘记更新高度和返回T}
接下来便是最关键的单旋转和双旋转操作,就像上面那样,即使判断出了高度差大于1了,那该怎么做使这个节点满足AVL树的性质呢?
- 单旋转
先考虑第一种情况,对节点k2的左儿子的 左子树 进行插入,使节点k2的左子树的高度k2右子树的高度高了2。
左边是最简单的情况,当然了,k2也可能有右子树,k1也可能有右子树,所以都可以归结为中间那个图的情况,X Y Z是子树,Y和Z可能为空树,但不管怎样,k2的左子树一定比右子树高2.
因此可以把k2这个节点降一层,k1这个节点升高一层,并改变一下Y的位置,就得到了最右边的图,这个过程就是SingleRotateWithLeft(T)。
Position SingleRotateWithLeft(Position K2){ Position K1; K1=K2->Left; //要将K1的位置记录下来 K2->Left=K1->Right; K1->Right=K2; /*不要忘记更新节点的高度*/ K2->Height=Max( Height( K2->Left), Height(K2->Right)) +1; K1->Height=Max( Height( K1->Left), Height(K1->Right)) +1; //注意先更新K2,然后再更新 K1 ,因为 K1的高度得到与 K2有关 return K1; //返回新的根 }
若对k2的右儿子的右子树进行插入,会出现下图所示的不平衡
可以看出,这种情况是与前一种对称的,所以有类似的过程:
Position SingleRotateWithRight(Position K2){ Position K1; K1=K2->Right; K2->Right=K1->Left; K1->Left=K2; K2->Height=Max( Height( K2->Left), Height(K2->Right)) +1; K1->Height=Max( Height( K1->Left), Height(K1->Right)) +1; return K1; }
- 双旋转
现在还剩下两种情况,插入的元素比k2的右子树k1的值要小或者比K2的左子树K1的值要大。显然这两种情况也是对称的,考虑左边的情况。
若还是对K2进行单旋转,即让K1成为新的根,又会变成类似右图的那种情况,X还是太深(K1上升1层,K2下降一层,X的层数还是没变)不满足AVL树的条件。必须找到新的能作为新的根的节点。
由于有一个节点插入了子树X,因此X非空,所以通过变换可以让K3成为新的根。对于变换,只需要进行两次旋转即可。第一次对K1单旋转使K1降一层,K3升一层,第二次对K2进行单旋转,让K2也降了一层,使K3成为新的根。
Position DoubleRotateWithLeft(Position K2){ K2->Left = SingleRotateWithRight(K2->Left); return SingleRotateWithLeft(K2);}Position DoubleRotateWithRight(Position K2){ K2->Right = SingleRotateWithLeft(K2->Right); return SingleRotateWithRight(K2);}
- 删除操作
下面来考虑删除操作,对于一个Avl树,节点的删除一般是下面三种情况A(树叶),B(只有一边的子树),C(左子树和右子树都有)。想一想可知,对于AB类型的正常删除即可,删除后仍然满足平衡树的性质。而对于C的情况,每一次执行删除操作后,只需判断一下是否(Height(T->Left) - Height(T->Right) == 2)即可,是的话执行相应的旋转即可。
AvlTree Delete(int X, AvlTree T){ if(T==NULL){ return NULL; }else if (T->x > X){ T->Left=Delete(X, T->Left); }else if (T->x < X){ T->Right=Delete(X, T->Right); }else { if (T->Left!=NULL && T->Right!=NULL){ AvlTree temp=FindMin(T->Right); T->x=temp->x; T->Right=Delete(T->x, T->Right); //删除后如果破坏了平衡便做相应的旋转 if(Height(T->Left) - Height(T->Right) == 2){ if (Height(T->Left->Left) > Height(T->Left->Right)){ T = SingleRotateWithLeft(T); }else{ T = DoubleRotateWithLeft(T); } } }else { //正常的删除操作 AvlTree temp=T; if (T->Left==NULL){ T = T->Right; }else if (T->Right==NULL){ T = T->Left; } free(temp); } } if (T!=NULL) T->Height = Max(Height(T->Left), Height(T->Right)) + 1; //不是树叶被删除的话要更新一下高度 return T;}
阅读全文
0 0
- AVL树的基本操作
- AVL树的基本操作
- AVL树的基本操作 HDU_4006 AVL树解法
- AVL树基本操作
- AVL树的定义和基本操作
- AVL---平衡二叉树的基本操作
- AVL树的基本操作 C++
- 平衡二叉树(AVL树)的基本操作
- 平衡二叉树AVL的基本操作之插入
- 平衡二叉树AVL的基本操作之删除
- 平衡二叉树(AVL)的介绍及基本操作
- 标题:AVL树的基本操作例程(1)
- Avl树的基本操作(c语言实现)
- AVL树的基本实现
- AVL树的基本实现
- AVL树的基本结构
- AVL树构建代码及其基本操作
- 二叉查找树和AVL树的基本操作(AVL树就是一颗特殊的二叉查找树。)
- 程序员应该掌握的省市联动
- 如何批量修改sql中某个字段中的特定信息
- 总结Qt5调用windows本地程序的三个方法以及异同
- 关于plsql远程连接oracle,以及连接64位oracle处理方法
- 面向初学者的XCP——测量/校准协议是什么?
- AVL树的基本操作
- [非技术]读书杂记
- 数据结构-树
- 用 Opencv 和 Python 对狗狗做模糊检测
- Ubuntu 16.04下安装SQL Server for Linux
- 静态链表相关算法学习
- jsTree使用记录
- JDBC详解系列(二)之加载驱动
- 12-23三道题