AVL树(命名来源于作者姓名,Adelson-Velskii和Landis),即平衡二叉树,满足以下的条件:

1)它的左子树和右子树都是AVL树

2)左子树和右子树的高度差不能超过1

从条件1可能看出是个递归定义。

AVL树中任何节点的两个儿子子树的高度最大差别为一,所以它也被称为高度平衡树。

AVL树插入节点的步骤,分为2类:

第1类:外侧插入,单旋转

第2类:内侧插入,双旋转(先旋转成外侧插入的情况,再单旋转)

由于调整以后,树高与插入前是相同的,所以无需再向上查看balance情况

代码实现:http://blog.chinaunix.net/uid-20662820-id-142440.html

struct node
{
node* parent;
node* left;
node* right;
int balance; //左右子树高度之差
int key;
}; int searchNode(int key, node* root, node** parent) //如果没找到,parent也是指向要插入位置的父位置
{
node* temp;
assert(root != NULL);
temp = root;
*parent = root->parent;
while (temp !=NULL)
{
if (temp->key == key)
return ;
else
{
*parent = temp;
if (temp->key > key)
temp = temp->left;
else
temp = temp->right;
}
}
return ;
} node* adjustAVL(node* root, node* parent, node* child)
{
node *cur;
assert((parent != NULL)&&(child != NULL));
switch (parent->balance)
{
case :
if (child->balance == -)//LR型(内侧插入):插入的节点的父节点直接升级做parent
{
cur = child->right;
cur->parent = parent->parent;
child->right = cur->left;
if (cur->left != NULL)
cur->left->parent = child;
parent->left = cur->right;
if (cur->right != NULL)
cur->right->parent = parent;
cur->left = child;
child->parent = cur;
cur->right = parent;
if (parent->parent != NULL)
if (parent->parent->left == parent)
parent->parent->left = cur;
else parent->parent->right = cur;
else
root = cur;
parent->parent = cur;
if (cur->balance == )
{
parent->balance = ;
child->balance = ;
}
else if (cur->balance == -)
{
parent->balance = ;
child->balance = ;
}
else
{
parent->balance = -;
child->balance = ;
}
cur->balance = ;
}
else //LL型(外侧插入):插入的节点的父节点升级做child,child升级做parent
child->parent = parent->parent;
parent->left = child->right;
if (child->right != NULL)
child->right->parent = parent;
child->right = parent;
if (parent->parent != NULL)
if (parent->parent->left == parent)
parent->parent->left = child;
else parent->parent->right = child;
else
root = child;
parent->parent = child;
if (child->balance == ) //插入时
{
child->balance = ;
parent->balance = ;
}
else //删除时
{
child->balance = -;
parent->balance = ;
}
}
break; case -:
if (child->balance == ) //RL型
{
cur = child->left;
cur->parent = parent->parent;
child->left = cur->right;
if (cur->right != NULL)
cur->right->parent = child;
parent->right = cur->left;
if (cur->left != NULL)
cur->left->parent = parent;
cur->left = parent;
cur->right = child;
child->parent = cur;
if (parent->parent != NULL)
if (parent->parent->left == parent)
parent->parent->left = cur;
else parent->parent->right = cur;
else
root = cur;
parent->parent = cur;
if (cur->balance == )
{
parent->balance = ;
child->balance = ;
}
else if (cur->balance == )
{
parent->balance = ;
child->balance = -;
}
else
{
parent->balance = ;
child->balance = ;
}
cur->balance = ;
}
else //RR型
{
child->parent = parent->parent;
parent->right = child->left;
if (child->left != NULL)
child->left->parent = parent;
child->left = parent;
if (parent->parent != NULL)
if (parent->parent->left == parent)
parent->parent->left = child;
else parent->parent->right = child;
else
root = child;
parent->parent = child;
if (child->balance == -) //插入时
{
child->balance = ;
parent->balance = ;
}
else //删除时
{
child->balance = ;
parent->balance = -;
}
}
break;
}
return root;
} node* insertNode(int key, node* root)
{
node *parent, *cur, *child;
assert (root != NULL);
if (searchNode(key, root, &parent)) //结点已存在
return root;
else
{
cur = (node*)malloc(sizeof(node));
cur->parent = parent;
cur->key = key;
cur->left = NULL;
cur->right = NULL;
cur->balance = ;
if (keykey)
{
parent->left = cur;
child = parent->left;
}
else
{
parent->right = cur;
child = parent->right;
} while ((parent != NULL)) //查找需要调整的最小子树
{
if (child == parent->left)
if (parent->balance == -)
{
parent->balance = ;
return root;
}
else if (parent->balance == )
{
parent->balance = ;
break;
}
else
{
parent->balance = ;
child = parent;
parent = parent->parent;
}
else if (parent->balance == ) //是右孩子,不会引起不平衡
{
parent->balance = ;
return root;
}
else if (parent->balance == -) //是右孩子,并且引起parent的不平衡
{
parent->balance = -;
break;
}
else //是右孩子,并且可能引起parent的parent的不平衡
{
parent->balance = -;
child = parent;
parent = parent->parent;
}
} if (parent == NULL)
return root;
return adjustAVL(root, parent, child);
}
}

平衡二叉树之AVL树的更多相关文章

  1. 【Java】 大话数据结构(12) 查找算法(3) (平衡二叉树(AVL树))

    本文根据<大话数据结构>一书及网络资料,实现了Java版的平衡二叉树(AVL树). 平衡二叉树介绍 在上篇博客中所实现的二叉排序树(二叉搜索树),其查找性能取决于二叉排序树的形状,当二叉排 ...

  2. Java数据结构(十四)—— 平衡二叉树(AVL树)

    平衡二叉树(AVL树) 二叉排序树问题分析 左子树全部为空,从形式上看更像一个单链表 插入速度没有影响 查询速度明显降低 解决方案:平衡二叉树 基本介绍 平衡二叉树也叫二叉搜索树,保证查询效率较高 它 ...

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

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

  4. 数据结构之平衡二叉树(AVL树)

    平衡二叉树(AVL树)定义如下:平衡二叉树或者是一棵空树,或者是具有以下性质的二叉排序树: (1)它的左子树和右子树的高度之差绝对值不超过1: (2)它的左子树和右子树都是平衡二叉树. AVL树避免了 ...

  5. 二叉树学习笔记之经典平衡二叉树(AVL树)

    二叉查找树(BSTree)中进行查找.插入和删除操作的时间复杂度都是O(h),其中h为树的高度.BST的高度直接影响到操作实现的性能,最坏情况下,二叉查找树会退化成一个单链表,比如插入的节点序列本身就 ...

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

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

  7. 平衡二叉树(AVL树)

    参考资料 http://www.cnblogs.com/Cmpl/archive/2011/06/05/2073217.html http://www.cnblogs.com/yc_sunniwell ...

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

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

  9. 经典平衡二叉树(AVL树)

    二叉查找树(BSTree)中进行查找.插入和删除操作的时间复杂度都是O(h),其中h为树的高度.BST的高度直接影响到操作实现的性能,最坏情况下,二叉查找树会退化成一个单链表,比如插入的节点序列本身就 ...

随机推荐

  1. SQL 中nvarchar和varchar到底能存多少汉字和英文

    实践出真知,在SQL中,nvarchar(50)表示汉字和英文都是50,varchar(50)汉字25,英文50

  2. 使用 Git 对原理图和线路板时行版本控制

    使用 Git 对原理图和线路板时行版本控制 由于之前一直用 Git 管理代码,我又开始试用 git 来对原理图和线路板时行版本控制. 由于 原理图和 PCB 的文件都是二进制文件,git 管理并不怎么 ...

  3. sqlzoo练习题答案

    title: SQL-Learning date: 2019-03-12 20:37:21 tags: SQL --- 这是关于在一个SQL学习网站的练习题答案记录:SQL教程 SQL基础 由一些简单 ...

  4. springMvc架构简介

    什么是spring 关于spring的定义无论是从官方还是市面上已经很多能够清晰明了的做出解释了.我姑且简单定义它为一个轻量级的控制反转(IoC)和面向切面(AOP)的容器,Java 开发框架,至于控 ...

  5. 【学习记录】二分查找的C++实现,代码逐步优化

    二分查找的思想很简单,它是针对于有序数组的,相当于数组(设为int a[N])排成一颗二叉平衡树(左子节点<=父节点<=右子节点),然后从根节点(对应数组下标a[N/2])开始判断,若值& ...

  6. idea之jrebel热部署使用教程

    JRebel是一个J2EE热部署的工具.使用它可以减少浪费8-18%的开发时间在项目的构建和部署上.虽然Java也提供了HotSpot的JVM,但是如果你修改的类中有方法名称变动的话,HotSpot就 ...

  7. 部署docker

    部署和开发环境不一样,我们不需要频繁地进入到容器内部,所以一般我们会将代码和环境打包到一块,部署到服务器上 Clone 代码 将项目代码克隆到本地 git clone git@git.coding.n ...

  8. .NET的URL重写

    [概述] URL重写就是首先获得一个进入的URL请求然后把它重新写成网站可以处理的另一个URL的过程.重写URL是非常有用的一个功能,因为它可以让你提高搜索引擎阅读和索引你的网站的能力:而且在你改变了 ...

  9. windows平台最简单的rtmp/hls流媒体服务器

    feature: rtmp/hls live server for windows, double click to run,don't need config. run and quit: doub ...

  10. Java编程打印出1000以内所有的完数

    /*如果一个数等 于其所有因子之和,我们就称这个数为"完数" * 例如6的因子为1,2,3, 6=1+2+3, 6就是一一个完数. * 请编程打印出1000以内所有的完数*/ pu ...