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. PHP面向对象——三大基本特性与五大基本原则

    三大特性是:封装.继承.多态 所谓封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏. 封装是面向对象的特征之一,是对象和类概念的主要特 ...

  2. PPP PDP 及GPRS

    1.相关概念: PDP:Packet Data Protocol 分组数据协议 PLMN:Public Land Mobile Network,公共陆地移动网络 APN:Access Point Na ...

  3. java代码--------打印三角形

    总结:这里主要是for循环里的j<=i而不死j<=i-1;.还有先打印“*” 再打印空格.换行.理解.请用脑子啊 package com.sads; public class Dds { ...

  4. [转] Jsp 重点

    讲师:传智播客 方立勋 4个域对象: pageContext | page 域 request | request 域 session | session 域 servletContext | app ...

  5. [转]Winform 经验集

    多线程篇: CheckForIllegalCrossThreadCalls = false; 更多示例可见: http://www.cnblogs.com/z5337/p/4030287.html i ...

  6. supervisor 管理

    Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启.它是通过fork/exec的方式把这些被管理的进程 ...

  7. 关于最大传输单元(MTU)的整理

    MTU设置不当,可能会导致许多网络问题,如某些网络应用无法使用,某些网站无法访问等.下面是在网上搜索整理的关于MTU设置的东西,某些可能未作验证,仅供参考. 1. 如何确定网络MTU 某些ISP接入的 ...

  8. canvas之画一个三角形

    <canvas id="canvas" width="500" height="500" style="background ...

  9. Sqoop修改sqoop元信息实现job的增量导入

    最简单方式是按主键增量导入:http://blog.csdn.net/ggz631047367/article/details/50185319 以下方法只做存档 需求:redis缓存的数据隔段时间往 ...

  10. 【洛谷】P2983 [USACO10FEB]购买巧克力Chocolate Buying(贪心)

    题目描述 Bessie and the herd love chocolate so Farmer John is buying them some. The Bovine Chocolate Sto ...