平衡二叉树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),存在于完全二叉排序树情况下,其访 ...
随机推荐
- jquery-lazyload延迟加载图片
下载地址:https://github.com/tuupola/jquery_lazyload用法:头部引用<script src="jquery.js" type=&quo ...
- debian下使用Sphinx异常“Could not import extension sphinx.builders.linkcheck (exception: cannot import name SSLError)”的解决
最近使用到Sphinx编译文档,出现如下异常: Extension error:Could not import extension sphinx.builders.linkcheck (except ...
- nginx 各类网站设置 (laravel , thinkphp , nodejs , https)
基础部分设置 [root@centos ~]# vim /opt/nginx/conf/nginx.conf user www www;worker_processes auto;pid logs/n ...
- MySQL选择合适的数据类型
一.char和varchar char是固定长度的,查询速度比varchar速度快的多.char的缺点是浪费存储空间. 检索char列时,返回的结果会删除尾部空格,所以程序需要对为空格进行处理. 对于 ...
- iOS程序模块化设计
一.模块化设计的概述: 模块化设计(Block-based design):对一定范围内的不同功能或相同功能的不同性能.不同规格的产品进行功能分析的基础上,划分并设计出一系列功能模块,通过模块的选择和 ...
- Unity学习疑问记录之协程
http://blog.csdn.net/huang9012/article/details/38492937 总结:1.协程相当于多线程但不是,(尽管它们看上去是这样的),它们运行在同一线程中,跟普 ...
- 什么情况下才要重写Objective-C中的description方法
特别注意: 千万不要在description方法中同时使用%@和self,同时使用了%@和self,代表要调用self的description方法,因此最终会导致程序陷入死循环,循环调用descrip ...
- Amoeba -- 阿里巴巴工程师的开源项目之一陈思儒
http://www.kuqin.com/opensource/20081023/24026.html 个人博客 http://dbanotes.net/web/page/44 阿里巴巴分布式服务框架 ...
- js微博发布框的实现
观察了微博发布框, 1.发现他的剩余文字是动态改变的, 2.且文字为零时 发布框颜色为暗色 3.文字不符合标准时提交不通过 整理了一下思路 js会主要用到的方法 1.onclick() //点击发布时 ...
- Expert 诊断优化系列------------------透过等待看系统
上一篇我们简单的介绍了,语句优化的三板斧,大部分语句三板斧过后,就算不成为法拉利也能是个宝马了.为了方便阅读给出系列文章的导读链接: SQL SERVER全面优化-------Expert for S ...