平衡二叉树AVL插入
平衡二叉树(Balancedbinary tree)是由阿德尔森-维尔斯和兰迪斯(Adelson-Velskiiand Landis)于1962年首先提出的,所以又称为AVL树。
定义:平衡二叉树或为空树,或为如下性质的二叉排序树:
(1)左右子树深度之差的绝对值不超过1;
(2)左右子树仍然为平衡二叉树.
平衡二叉树可以避免排序二叉树深度上的极度恶化,使树的高度维持在O(logn)来提高检索效率。
因为插入节点导致整个二叉树失去平衡分成如下的四种情况:


假设由于在二叉排序树上插入节点而失去平衡的最小子数根节点的指针为a(即a是离插入节点最近,且平衡因子绝对值超过1的祖先节点),则失去平衡后进行调整的规律如下:
1.如上图LL单向右旋处理:由于在*a的左子树根节点的左子树上插入节点,*a的平衡因子由1增至2,致使以*a为根节点的子树失去平衡,则需要进行一次向右的顺时针旋转操作。
2.如上图RR单向左旋处理:由于在*a的右子树根节点的右子树上插入节点, *a的平衡因子有-1变为-2,致使以*a为根节点的子树失去平衡,则学要进行一次向左的逆时针旋转操作。
3.如上图LR双向旋转(先左后右)处理:由于在*a的左子树根节点的右子树插入节点,*a的平衡因子有1增至2,致使以*a为根节点的子树失去平衡,则需要进行两次旋转(先左旋后右旋)操作。
4.如上图RL双向旋转(先右后左)处理:由于在*a的右子树根节点的左子树上插入节点,*a的平衡因子由-1变为-2,致使以*a为根节点的子树失去平衡,则需要进行两次旋转(先左旋后右旋)操作。
#include<iostream>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<cstdio>
#define LH 1 //左高
#define EH 0 //等高
#define RH -1 //右高
using namespace std; template <typename ElemType>
class BSTNode{
public:
ElemType data;//节点的数据
int bf;//节点的平衡因子
BSTNode *child[];
BSTNode(){
child[] = NULL;
child[] = NULL;
}
}; typedef BSTNode<string> BSTnode, *BSTree; template <typename ElemType>
class AVL{
public:
BSTNode<ElemType> *T;
void buildT();
void outT(BSTNode<ElemType> *T);
private:
bool insertAVL(BSTNode<ElemType>* &T, ElemType key, bool &taller);
void rotateT(BSTNode<ElemType>* &o, int x);//子树的左旋或者右旋
void leftBalance(BSTNode<ElemType>* &o);
void rightBalance(BSTNode<ElemType>* &o);
}; template <typename ElemType>
void AVL<ElemType>::rotateT(BSTNode<ElemType>* &o, int x){
BSTNode<ElemType>* k = o->child[x^];
o->child[x^] = k->child[x];
k->child[x] = o;
o = k;
} template <typename ElemType>
void AVL<ElemType>::outT(BSTNode<ElemType> *T){
if(!T) return;
cout<<T->data<<" ";
outT(T->child[]);
outT(T->child[]);
} template <typename ElemType>
void AVL<ElemType>::buildT(){
T = NULL;
ElemType key;
while(cin>>key){
if(key==) break;
bool taller = false;
insertAVL(T, key, taller);
outT(T);
cout<<endl;
}
} template <typename ElemType>
bool AVL<ElemType>::insertAVL(BSTNode<ElemType>* &T, ElemType key, bool &taller){
if(!T){//插入新的节点,taller=true 那么树的高度增加
T = new BSTNode<ElemType>();
T->data = key;
T->bf = EH;
taller = true;
} else {
if(T->data == key){
taller = false;
return false;
}
if(T->data > key){//向T的左子树进行搜索并插入
if(!insertAVL(T->child[], key, taller)) return false;
if(taller){//
switch(T->bf){
case LH://此时左子树的高度高,左子树上又插入了一个节点,失衡,需要进行调整
leftBalance(T);
taller = false;//调整之后高度平衡
break;
case EH:
T->bf = LH;
taller = true;
break;
case RH:
T->bf = EH;
taller = false;
break;
}
}
}
if(T->data < key) {//向T的右子树进行搜索并插入
if(!insertAVL(T->child[], key, taller)) return false;
switch(T->bf){
case LH:
T->bf = EH;
taller = false;
break;
case EH:
T->bf = RH;
taller = true;
break;
case RH:
rightBalance(T);
taller = false;
break;
}
}
}
return true;
} template <typename ElemType>
void AVL<ElemType>::leftBalance(BSTNode<ElemType>* &T){
BSTNode<ElemType>* lchild = T->child[];
switch(lchild->bf){//检查T的左子树的平衡度,并作相应的平衡处理
case LH://新节点 插入到 T的左孩子的左子树上,需要对T节点做单旋(右旋)处理
T->bf = lchild->bf = EH;
rotateT(T, );
break;
case RH://新节点 插入到 T的左孩子的右子树上,需要做双旋处理 1.对lchild节点进行左旋,2.对T节点进行右旋
BSTNode<ElemType>* rdchild = lchild->child[];
switch(rdchild->bf){//修改 T 及其左孩子的平衡因子
case LH: T->bf = RH; lchild->bf = EH; break;
case EH: T->bf = lchild->bf = EH; break;//发生这种情况只能是 rdchild无孩子节点
case RH: T->bf = EH; lchild->bf = LH; break;
}
rdchild->bf = EH;
rotateT(T->child[], );//不要写成 rotateT(lc, 0);//这样的话T->lchild不会改变
rotateT(T, );
break;
}
} template <typename ElemType>
void AVL<ElemType>::rightBalance(BSTNode<ElemType>* &T){
BSTNode<ElemType>* rchild = T->child[];
switch(rchild->bf){//检查T的左子树的平衡度,并作相应的平衡处理
case RH://新节点 插入到 T的右孩子的右子树上,需要对T节点做单旋(左旋)处理
T->bf = rchild->bf = EH;
rotateT(T, );
break;
case LH://新节点 插入到 T的右孩子的左子树上,需要做双旋处理 1.对rchild节点进行右旋,2.对T节点进行左旋
BSTNode<ElemType>* ldchild = rchild->child[];
switch(ldchild->bf){//修改 T 及其右孩子的平衡因子
case LH: T->bf = EH; rchild->bf = RH; break;
case EH: T->bf = rchild->bf = EH; break;//发生这种情况只能是 ldchild无孩子节点
case RH: T->bf = LH; rchild->bf = EH; break;
}
ldchild->bf = EH;
rotateT(T->child[], );
rotateT(T, );
break;
}
} int main(){
AVL<int> avl;
avl.buildT();
avl.outT(avl.T);
return ;
} /*
13 24 37 90 53 0
*/
平衡二叉树AVL插入的更多相关文章
- 平衡二叉树AVL - 插入节点后旋转方法分析
平衡二叉树 AVL( 发明者为Adel'son-Vel'skii 和 Landis)是一种二叉排序树,其中每一个节点的左子树和右子树的高度差至多等于1. 首先我们知道,当插入一个节点,从此插入点到树根 ...
- 二叉查找树(BST)、平衡二叉树(AVL树)(只有插入说明)
二叉查找树(BST).平衡二叉树(AVL树)(只有插入说明) 二叉查找树(BST) 特殊的二叉树,又称为排序二叉树.二叉搜索树.二叉排序树. 二叉查找树实际上是数据域有序的二叉树,即对树上的每个结点, ...
- 平衡二叉树AVL删除
平衡二叉树的插入过程:http://www.cnblogs.com/hujunzheng/p/4665451.html 对于二叉平衡树的删除采用的是二叉排序树删除的思路: 假设被删结点是*p,其双亲是 ...
- 平衡二叉树,AVL树之图解篇
学习过了二叉查找树,想必大家有遇到一个问题.例如,将一个数组{1,2,3,4}依次插入树的时候,形成了图1的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建 ...
- 数据结构与算法--从平衡二叉树(AVL)到红黑树
数据结构与算法--从平衡二叉树(AVL)到红黑树 上节学习了二叉查找树.算法的性能取决于树的形状,而树的形状取决于插入键的顺序.在最好的情况下,n个结点的树是完全平衡的,如下图"最好情况&q ...
- K:平衡二叉树(AVL)
相关介绍: 二叉查找树的查找效率与二叉树的形状有关,对于按给定序列建立的二叉排序树,若其左.右子树均匀分布,则查找过程类似于有序表的二分查找,时间复杂度变为O(log2n).当若给定序列原来有序,则 ...
- 平衡二叉树(AVL)的理解和实现(Java)
AVL的定义 平衡二叉树:是一种特殊的二叉排序树,其中每一个节点的左子树和右子树的高度差至多等于1.从平衡二叉树的名字中可以看出来,它是一种高度平衡的二叉排序树.那么什么叫做高度平衡呢?意思就是要么它 ...
- 平衡二叉树,AVL树之代码篇
看完了第一篇博客,相信大家对于平衡二叉树的插入调整以及删除调整已经有了一定的了解,下面,我们开始介绍代码部分. 首先,再次提一下使用的结构定义 typedef char KeyType; //关键字 ...
- 二叉查找树、平衡二叉树(AVL)、B+树、联合索引
1. [定义] 二叉排序树(二拆查找树)中,左子树都比节点小,右子树都比节点大,递归定义. [性能] 二叉排序树的性能取决于二叉树的层数 最好的情况是 O(logn),存在于完全二叉排序树情况下,其访 ...
随机推荐
- 利用CORS实现跨域请求(转载)
跨域请求一直是网页编程中的一个难题,在过去,绝大多数人都倾向于使用JSONP来解决这一问题.不过现在,我们可以考虑一下W3C中一项新的特性--CORS(Cross-Origin Resource Sh ...
- C#输出文本树形层次,前或者后自定义空格位数
Indent String with Spaces This example shows how to indent strings using method for padding in C#. T ...
- 【Telerik】实现列表单元格中添加复选框,进行状态(是、否)判断
前台界面: 需求:实现对每条细则是否必备进行判断,必备就勾选,否则不勾选. 首先:要保证列表GridView是可编辑的(IsReadOnly=false) 表格代码 其次:单元格的数据绑定要保证是双向 ...
- 可变数组NSMutableArray
//创建一个空的可变数组 NSMutableArray *array = [NSMutableArray array]; //向数组里面添加对象 [array addObject:@"< ...
- [IOS]swift 使用AVOS的API
避免写后台代码,但保证app能够有后台,使用了AVOS这个产品来帮助自己的app联网,AVOS是很强大的云服务,基本原理和Parse差不多,只是parse在国外可能对国内用户联网速度上有点限制. 下面 ...
- python 之 Django 小案例
一, F Q # F 使用查询条件的值 # # from django.db.models import F # models.Tb1.objects.update(num=F('num')+1) ...
- hadoop分布式存储(2)-hadoop的安装(毕业设计)
总共分三步:1.准备linux环境 租用"云主机",阿里云,unitedStack等,云主机不受本机性能影响(或者直接安转linux操作系统或者虚拟机也行): PuTTy Conf ...
- cocos2d中各种action方法的应用
Action示例: 1.移动动作 cc.MoveBy:create(time, posX, posY) 在time时间内,相对当前位置基础上移动x,y个单位. cc.MoveTo:create(ti ...
- poj1200-Crazy Search(hash入门经典)
Hash:一般是一个整数.就是说通过某种算法,可以把一个字符串"压缩" 成一个整数.一,题意: 给出两个数n,nc,并给出一个由nc种字符组成的字符串.求这个字符串中长度为n的不同 ...
- Python黑帽编程 2.0 第二章概述
Python黑帽编程 2.0 第二章概述 于 20世纪80年代末,Guido van Rossum发明了Python,初衷据说是为了打发圣诞节的无趣,1991年首次发布,是ABC语言的继承,同时也是一 ...