一步一步编写AVL树
第一步:定义结构体
typedef struct Node{
int d; //data
int h=; //height
struct Node* l=NULL;
struct Node* r=NULL;
Node(int d=):d(d){
}
}Node;
这个结构体和常规的二叉树结构体很相似。但是不同的是多了个属性“h”(height)。用这个属性来记录结点的高度,叶子结点为1,空结点为0 。
第二部:编写BST树的插入函数
Node* insert(Node* p,int v){
Node * node=new Node(v);
if(!p){
return node;
}
if(v < p->d){ //左子树
if(p->l){
p->l=insert(p->l,v);
}else{
p->l=node;
}
}else{
if(p->r){
p->r=insert(p->r,v);
}else{
p->r=node;
}
}
// setHeight(p);
//平衡旋转代码
//end of 平衡旋转代码
return p;
}
第三步:编写高度获取与设置的辅助函数
高度获取:
int getHeight(Node* node){
if(node) return node->h; //如果非空返回这个结点的height
return ; //空节点的高度是0
}
高度设置:
void setHeight(Node* node){ //取左右子树高度的最大值,记得+1
node->h=max(getHeight(node->l),getHeight(node->r))+;
}
第四步:编写平衡旋转函数
当左右子树的height相差为2时,就要调用平衡旋转函数进行旋转。一共有4种旋转模式:
(注:一下图片采用自博客:http://www.cnblogs.com/Camilo/p/3917041.html,如果侵权请联系我删除)
左子树左结点引起的不平衡:
Node* LL(Node* node){
Node* re=node->l;
node->l=re->r;
re->r=node;
setHeight(node); //注意:先进行这一步。因为node是re的子结点,从下往上调整
setHeight(re);
return re;
}

右子树右结点引起的不平衡:
Node* RR(Node* node){
Node* re=node->r;
node->r=re->l;
re->l=node;
setHeight(node);
setHeight(re);
return re;
}
(注:编写技巧是在LL函数的基础上,把所有的r写成l,把所有的l写成r,轮换对称思想)

左子树右结点引起的不平衡:
Node* LR(Node* node){
node->l=RR(node->l);
node=LL(node);
return node;
}

右子树左结点引起的不平衡:
Node* RL(Node* node){
node->r=LL(node->r);
node=RR(node);
return node;
}

第五步:在BST树的插入函数中编写平衡旋转代码:
Node* insert(Node* p,int v){
Node * node=new Node(v);
if(!p){
return node;
}
if(v < p->d){ //左子树
if(p->l){
p->l=insert(p->l,v);
}else{
p->l=node;
}
}else{
if(p->r){
p->r=insert(p->r,v);
}else{
p->r=node;
}
}
setHeight(p);
//平衡旋转代码
if(getHeight(p->l)-getHeight(p->r)==){ //左子树不平衡
if(getHeight(p->l->l)>getHeight(p->l->r)){//左结点不平衡
p=LL(p);
}else{ //右结点不平衡
p=LR(p);
}
}
if(getHeight(p->r)-getHeight(p->l)==){ //右子树不平衡
if(getHeight(p->r->l)>getHeight(p->r->r)){//左结点不平衡
p=RL(p);
}else{ //右结点不平衡
p=RR(p);
}
}
//end of 平衡旋转代码
return p;
}
打个OJ测试一下:1123. Is It a Complete AVL Tree
AC代码:
#include <stdio.h>
#include <queue>
#include <algorithm> using namespace std; typedef struct Node{
int d; //data
int h=; //height
struct Node* l=NULL;
struct Node* r=NULL;
Node(int d=):d(d){
}
}Node; int getHeight(Node* node){
if(node) return node->h; //如果非空返回这个结点的height
return ; //空节点的高度是0
} void setHeight(Node* node){ //取左右子树高度的最大值,记得+1
node->h=max(getHeight(node->l),getHeight(node->r))+;
} Node* LL(Node* node){
Node* re=node->l;
node->l=re->r;
re->r=node;
setHeight(node); //注意:先进行这一步。因为node是re的子结点,从下往上调整
setHeight(re);
return re;
} Node* RR(Node* node){
Node* re=node->r;
node->r=re->l;
re->l=node;
setHeight(node);
setHeight(re);
return re;
} Node* LR(Node* node){
node->l=RR(node->l);
node=LL(node);
return node;
} Node* RL(Node* node){
node->r=LL(node->r);
node=RR(node);
return node;
} Node* insert(Node* p,int v){
Node * node=new Node(v);
if(!p){
return node;
}
if(v < p->d){ //左子树
if(p->l){
p->l=insert(p->l,v);
}else{
p->l=node;
}
}else{
if(p->r){
p->r=insert(p->r,v);
}else{
p->r=node;
}
}
setHeight(p);
//平衡旋转代码
if(getHeight(p->l)-getHeight(p->r)==){ //左子树不平衡
if(getHeight(p->l->l)>getHeight(p->l->r)){//左结点不平衡
p=LL(p);
}else{ //右结点不平衡
p=LR(p);
}
}
if(getHeight(p->r)-getHeight(p->l)==){ //右子树不平衡
if(getHeight(p->r->l)>getHeight(p->r->r)){//左结点不平衡
p=RL(p);
}else{ //右结点不平衡
p=RR(p);
}
}
//end of 平衡旋转代码
return p;
} int cnt=; int main(){
// freopen("I:\\pat\\树\\AVL\\1123_2.txt","r",stdin);
int n,t;
scanf("%d",&n);
Node * root;
for(int i=;i<n;i++){
scanf("%d",&t);
root=insert(root,t);
}
queue<Node*> q;
q.push(root);
bool findNull=;
bool yes=;
bool after=;
while(!q.empty()){
Node* t=q.front();
q.pop();
printf("%d",t->d);
cnt++;
if(cnt!=n)
printf(" ");
if(t->l){
q.push(t->l);
if(after) yes=;
}
else after=;
if(t->r){
q.push(t->r);
if(after) yes=;
}
else after=;
}
puts("");
puts(yes?"YES":"NO");
return ;
}
一步一步编写AVL树的更多相关文章
- 一步一步写平衡二叉树(AVL树)
平衡二叉树(Balanced Binary Tree)是二叉查找树的一个进化体,也是第一个引入平衡概念的二叉树.1962年,G.M. Adelson-Velsky 和 E.M. Landis发明了这棵 ...
- AVL树的插入与删除
AVL 树要在插入和删除结点后保持平衡,旋转操作必不可少.关键是理解什么时候应该左旋.右旋和双旋.在Youtube上看到一位老师的视频对这个概念讲解得非常清楚,再结合算法书和网络的博文,记录如下. 1 ...
- 一步一步教你编写与搭建自动化测试框架——python篇
[本文出自天外归云的博客园] 这两天用python写了一个自动化测试框架,取名为Auty.准备用来做Web方面的接口测试,以下为Auty框架一步一步的搭建过程——
- 一步一步理解线段树——转载自JustDoIT
一步一步理解线段树 目录 一.概述 二.从一个例子理解线段树 创建线段树 线段树区间查询 单节点更新 区间更新 三.线段树实战 -------------------------- 一 概述 线段 ...
- 算法与数据结构(十一) 平衡二叉树(AVL树)
今天的博客是在上一篇博客的基础上进行的延伸.上一篇博客我们主要聊了二叉排序树,详情请戳<二叉排序树的查找.插入与删除>.本篇博客我们就在二叉排序树的基础上来聊聊平衡二叉树,也叫AVL树,A ...
- AVL树的平衡算法(JAVA实现)
1.概念: AVL树本质上还是一个二叉搜索树,不过比二叉搜索树多了一个平衡条件:每个节点的左右子树的高度差不大于1. 二叉树的应用是为了弥补链表的查询效率问题,但是极端情况下,二叉搜索树会无限接近 ...
- 【数据结构】平衡二叉树—AVL树
(百度百科)在计算机科学中,AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下都是O(log n).增 ...
- 我的新发现:AVL树旋转的一个特性
关于AVL树旋转的代码网络上铺天盖地. 一些经典的实现方法如下: AVLTree SingleLeftRotation(AVLTree A) { AVLTree B = A->left; A-& ...
- 纸上谈兵:AVL树
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 二叉搜索树的深度与搜索效率 我们在树, 二叉树, 二叉搜索树中提到,一个有n个节点 ...
随机推荐
- Linux系统安装snmp服务
Linux安装snmp详解 Snmp一种网络之间的传输协议,通过snmp可以采集很多指标比如cpu.内存及磁盘的信息,现在越来越多的网络设备基本上都支持snmp,本文介绍了snmp的安装过程. 二.安 ...
- Jmeter参数化之数据库读取数据
以读取mysql数据库为例 1.下载一个mysql驱动包,最好去mysql官网下载 下载网址:https://dev.mysql.com/downloads/connector/j/ Select O ...
- 『Pushbox 点双联通分量』
Pushbox Description 周婧涵和她的小伙伴们发明了一个新游戏.游戏名字很准确,但不是特别有 创意.她们称之为"推动箱子在谷仓周围找到正确的位置,不要移动干草"游戏 ...
- Java 8——Base64工具
在java 8之前如果需要使用base64编解码,必须使用三方库,如:apache的commons-codec. 但是java 8将base64编解码的工具引入进来: public class Tes ...
- 一次U9身份验证http数据对接
一般情况下传输和回传HTTP协议就搞定了,但这次不同,有身份验证,网上的资料相对较少,怎么办呢?.NET没有不代表JAVA没有,网上搜JAVA身份验证HTTP协议, 果然是有的,跟着代码改成相应的.N ...
- 简单理解ORM,实体类生成查询SQL语句
目前有很多开源的ORM项目,大多情况下也不需要我们重复去造轮子,我们只需要了解轮子怎么造的,怎么用就可以,下面简单说一下怎么通过实体生成一个SQL语句: 先建立2个Attribute类,TableAt ...
- mvc5中webapi的路由
1.Global.asax中路由的注册 public class WebApiApplication : System.Web.HttpApplication { protected void App ...
- tkinter事件键盘绑定
tkinter事件键盘绑定 from tkinter import * root=Tk() #创建一个框架,在这个框架中响应事件 frame=Frame(root, width=200,height= ...
- iis url 重写
1.选择网站-找到有测url 重写 :2:选中它,在右上角有一个打开功能,点击打开 3.依然在右上角,点击添加规则 4:选择第一个,空白规则 名称随便输入,我们通常有这样一个需求,就是.aspx 后缀 ...
- QML MultiPointTouchArea
MultiPointTouchArea为qml中的多点触摸提供了最基本.最重要的支持,它与TouchPoint及相关域结合,可以说是qml中多点触摸的基石. MultiPointTouchArea是不 ...