第一步:定义结构体

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树的更多相关文章

  1. 一步一步写平衡二叉树(AVL树)

    平衡二叉树(Balanced Binary Tree)是二叉查找树的一个进化体,也是第一个引入平衡概念的二叉树.1962年,G.M. Adelson-Velsky 和 E.M. Landis发明了这棵 ...

  2. AVL树的插入与删除

    AVL 树要在插入和删除结点后保持平衡,旋转操作必不可少.关键是理解什么时候应该左旋.右旋和双旋.在Youtube上看到一位老师的视频对这个概念讲解得非常清楚,再结合算法书和网络的博文,记录如下. 1 ...

  3. 一步一步教你编写与搭建自动化测试框架——python篇

    [本文出自天外归云的博客园] 这两天用python写了一个自动化测试框架,取名为Auty.准备用来做Web方面的接口测试,以下为Auty框架一步一步的搭建过程——

  4. 一步一步理解线段树——转载自JustDoIT

    一步一步理解线段树   目录 一.概述 二.从一个例子理解线段树 创建线段树 线段树区间查询 单节点更新 区间更新 三.线段树实战 -------------------------- 一 概述 线段 ...

  5. 算法与数据结构(十一) 平衡二叉树(AVL树)

    今天的博客是在上一篇博客的基础上进行的延伸.上一篇博客我们主要聊了二叉排序树,详情请戳<二叉排序树的查找.插入与删除>.本篇博客我们就在二叉排序树的基础上来聊聊平衡二叉树,也叫AVL树,A ...

  6. AVL树的平衡算法(JAVA实现)

      1.概念: AVL树本质上还是一个二叉搜索树,不过比二叉搜索树多了一个平衡条件:每个节点的左右子树的高度差不大于1. 二叉树的应用是为了弥补链表的查询效率问题,但是极端情况下,二叉搜索树会无限接近 ...

  7. 【数据结构】平衡二叉树—AVL树

    (百度百科)在计算机科学中,AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下都是O(log n).增 ...

  8. 我的新发现:AVL树旋转的一个特性

    关于AVL树旋转的代码网络上铺天盖地. 一些经典的实现方法如下: AVLTree SingleLeftRotation(AVLTree A) { AVLTree B = A->left; A-& ...

  9. 纸上谈兵:AVL树

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 二叉搜索树的深度与搜索效率 我们在树, 二叉树, 二叉搜索树中提到,一个有n个节点 ...

随机推荐

  1. 明解C语言 入门篇 第十章答案

    练习10-1 #include <stdio.h> void adjust_point(int*n) { ) *n = ; ) *n = 0; } int main() { int x; ...

  2. js 实现 promise

    本文仅用于个人技术记录,如误导他人,概不负责. 本文有参考其他文章,不过地址忘了~~~. ======================================================= ...

  3. python网络爬虫(1)——安装scrapy框架的常见问题及其解决方法

    Scrapy是为了爬取网站数据而编写的一款应用框架,出名,强大.所谓的框架其实就是一个集成了相应的功能且具有很强通用性的项目模板. 其实在Linux和 Mac安装,就简单的pip命令即可: pip i ...

  4. Portainer容器可视化管理工具使用文档

    本文内容 主要介绍下Portainer的Docker使用方式,基于当前最新版v1.22.1,使用Docker的本地部署,并连接另一台服务器进行测试,更多请参考官网https://www.portain ...

  5. 我遇到的WPF的坑

    转自 林德熙Blog 本文:我遇到的WPF的坑 目录 单例应用在多实例用户无法使用 标记方法被使用 当鼠标滑过一个被禁用的元素时,让ToolTip 显示 获取设备屏幕数量 获取当前域用户 绑定资源文件 ...

  6. webapi处理OPTIONS请求

    报错1信息 Access to XMLHttpRequest at 'http://localhost:4445/api/v/getmsg' from origin 'http://localhost ...

  7. Windows Server - 用tomcat部署finereport

    原博地址:https://blog.csdn.net/qq_39019865/article/details/80969728

  8. Mark: 实现个toy版的脚手架(RPC)

    p.s.  这些小toy的规模都在几百~上千行代码量,但足以反映一个tool的核心思想. 包括: 一些中间件(消息队列.Netty) Spring的IoC容器:(自动依赖注入) —— 就是利用Java ...

  9. wsl中的git问题

    当使用wsl打开Windows下的仓库时可能会出现所有文件都被标记为modified,这时一般有两种情况. 文件权限问题 由于wsl申请对文件的读写权限导致文件的权限发生改变.这时只需修改git的设置 ...

  10. 微服务架构 ------ 插曲 Linux平台 Ubuntu的安装

    1.一定要通过自定义安装 2.选择的硬件兼容性选择 14.x   这里介绍一下红框内的东西,是为了做虚拟存储使用的,也就是一批服务器对外展示位一个服务器,类似于服务器集群 3.选择稍后安装操作系统,如 ...