不同结构的二叉查找树,查找效率有很大的不同(单支树结构的查找效率退化成了顺序查找)。如何解决这个问题呢?关键在于如何最大限度的减小树的深度。正是基于这个想法,平衡二叉树出现了。

平衡二叉树的定义 (AVL—— 发明者为Adel’son-Vel’skii 和 Landis)

平衡二叉查找树,又称 AVL树。 它除了具备二叉查找树的基本特征之外,还具有一个非常重要的特点:它 的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值(平衡因子 ) 不超过1。 也就是说AVL树每个节点的平衡因子只可能是-1、0和1(左子树高度减去右子树高度)。

那么如何是二叉查找树在添加数据的同时保持平衡呢?基本思想就是:当在二叉排序树中插入一个节点时,首先检查是否因插入而破坏了平衡,若 破坏,则找出其中的最小不平衡二叉树,在保持二叉排序树特性的情况下,调整最小不平衡子树中节点之间的关系,以达 到新的平衡。所谓最小不平衡子树 指离插入节点最近且以平衡因子的绝对值大于1的节点作为根的子树。

平衡二叉树的操作

  • 查找操作

    平衡二叉树的查找基本与二叉查找树相同。

  • 插入操作

    在平衡二叉树中插入结点与二叉查找树最大的不同在于要随时保证插入后整棵二叉树是平衡的。那么调整不平衡树的基本方法就是: 旋转 。 下面我们归纳一下平衡旋转的4种情况:

    这里我们把必须重新平衡的节点叫做A。

    平衡因子:左子树的深度减去右子树的深度。

    相关旋转图示见 严蔚敏《数据结构》(C语言版)P235

    1. 单旋转–向右旋转平衡处理–在A的左儿子的左子树进行一次插入。此时平衡因子变为2。
    2. 单旋转–向左旋转平衡处理–在A的右儿子的右子树进行一次插入操作。此时平衡因子变为-2.
    3. 双旋转–先右后左旋转平衡处理–在A的左儿子的右子树进行一次插入操作。此时平衡因子变为2.
    4. 双旋转–先左后右平衡处理–在A的右儿子的左子树进行一次插入操作。此时平衡因子变为-2.

代码实现:

/**
*AVL 树 插入新节点 的实现
*/ struct AVLNode{
int val;
AVLNode* left;
AVLNode* right;
int height;
AVLNode(const int& value, AVLNode* lt, AVLNode* rt, int h = 0):val(value), left(lt),right(rt),height(h){}
}; /**
*Return thr height of node t ot -1 if NULL
* /
int height(AVLNode* t) const
{
return t == NULL ? -1 : t->height;
} void insert(const int& x, AVLNode* & t)
{
if(t == NULL) //empty Tree
t = new AVLNode(x, NULL, NULL);
else if(x < t->val) //插入到左儿子
{
//insert into left subtree
insert(x, t->left);
if(height(t->left) - height(t->right) == 2)
{
if(x < t->left->val) //插入到了左儿子的左子树中 ,向右单旋转
rotateWithLeftChild(t);
else //插入到左儿子的右子树, 先左后右双旋转
doubleRotateWithLeftChild(t);
}
}
else if(x > t->val) //插入到右儿子
{
insert(x, t->right);
if(height(t->right) - height(t->left) == 2)
{
if(x > t->right->val)
rotateWithRightChild(t); //插入到右儿子的右子树, 向左单旋转
else if(x < t->right->val)
doubleRotateWithRightChild(t); //插入到右儿子的左子树, 先右后左双旋转
}
}
else {
//待插入节点已经存在, do nothing
} t->height = max(height(t->left), height(t->right)) + 1;
} //向右单旋转
void rotateWithLeftChild( AVLNode* & root)
{
AVLNode *newRoot = root->left;
root->left = newRoot->right;
newRoot->right = root;
root->height = max(height(root->left), height(root->right)) + 1;
newRoot->height = max(height(newRoot->left), root->height) + 1;
root = newRoot; //root 指向新的root节点
} //向左单旋转
void rotateWithRightChild(AVLNode* & root)
{
AVLNode* newRoot = root->right;
root->right = newRoot->left;
newRoot->left = root;
root->height = max(height(root->left), height(root->right)) + 1;
newRoot->height = max(height(newRoot->right), root->height) + 1;
root = newRoot;
} //先左后右双旋转
void doubleRotateWithLeftChild(AVLNode* & root)
{
rotateWithRightChild(root->left); //先对root的左子树进行向左单旋转
rotateWithLeftChild(root); //然后对root进行向右单旋转
} //先右后左双旋转
void doubleRotateWithRightChild(AVLNode* & root)
{
rotateWithLeftChild(root->right); //先对root的右子树进行向右单旋转
rotateWithRightChild(root); //然后对root进行向左单旋转
}

平衡二叉树性能分析

平衡二叉树的性能优势:

很显然,平衡二叉树的优势在于不会出现普通二叉查找树的最差情况。其查找的时间复杂度为O(logN)。

在平衡树上进行查找的过程和二叉排序树相同,因此,在查找的过程中和给定值进行比较的关键字个数不超过树的深度。

那么,

含有n个关键字的平衡树的最大深度是多少呢?

为了解答这个问题,

可以借助 深度为h的平衡树所具有的最少节点数的计算公式:

最少节点数

S(h) = S(h - 1) + S(h - 2) + 1
其中,h = 0, S(h) = 1; h = 1, S(h) = 2.

得到h的最大值。

平衡二叉树的缺陷:

(1) 很遗憾的是,为了保证高度平衡,动态插入和删除的代价也随之增加。因此,我们在下一专题中讲讲《红黑树》 这种更加高效的查找结构。

(2) 所有二叉查找树结构的查找代价都与树高是紧密相关的,能否通过减少树高来进一步降低查找代价呢。我们可以通过多路查找树的结构来做到这一点,在后面专题中我们将通过《多路查找树/B-树/B+树 》来介绍。

(3) 在大数据量查找环境下(比如说系统磁盘里的文件目录,数据库中的记录查询 等),所有的二叉查找树结构(BST、AVL、RBT)都不合适。如此大规模的数据量(几G数据),全部组织成平衡二叉树放在内存中是不可能做到的。那么把这棵树放在磁盘中吧。问题就来了:假如构造的平衡二叉树深度有1W层。那么从根节点出发到叶子节点很可能就需要1W次的硬盘IO读写。大家都知道,硬盘的机械部件读写数据的速度远远赶不上纯电子媒体的内存。 查找效率在IO读写过程中将会付出巨大的代价。在大规模数据查询这样一个实际应用背景下,平衡二叉树的效率就很成问题了。对这一问题的解决:我们也会在《多路查找树/B-树/B+树 》 将详细分析。

上面提到的红黑树和多路查找树都是属于深度有界查找树(depth-bounded tree —DBT)

平衡二叉查找树 AVL 的实现的更多相关文章

  1. 【查找结构3】平衡二叉查找树 [AVL]

    在上一个专题中,我们在谈论二叉查找树的效率的时候.不同结构的二叉查找树,查找效率有很大的不同(单支树结构的查找效率退化成了顺序查找).如何解决这个问题呢?关键在于如何最大限度的减小树的深度.正是基于这 ...

  2. 006-数据结构-树形结构-二叉树、二叉查找树、平衡二叉查找树-AVL树

    一.概述 树其实就是不包含回路的连通无向图.树其实是范畴更广的图的特例. 树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合. 1.1.树的特性: 每个结点有零个或多个子 ...

  3. 面试题:什么叫平衡二叉查找树--AVL树

    查找.插入和删除在平均和最坏情况下都是O(log n) 增加和删除可能需要通过一次或多次树旋转来重新平衡这个树 节点的平衡因子是它的左子树的高度减去它的右子树的高度.带有平衡因子 1.0 或 -1 的 ...

  4. AVL树(平衡二叉查找树)

    首先要说AVL树,我们就必须先说二叉查找树,先介绍二叉查找树的一些特性,然后我们再来说平衡树的一些特性,结合这些特性,然后来介绍AVL树. 一.二叉查找树 1.二叉树查找树的相关特征定义 二叉树查找树 ...

  5. 平衡树初阶——AVL平衡二叉查找树+三大平衡树(Treap + Splay + SBT)模板【超详解】

    平衡树初阶——AVL平衡二叉查找树 一.什么是二叉树 1. 什么是树. 计算机科学里面的树本质是一个树状图.树首先是一个有向无环图,由根节点指向子结点.但是不严格的说,我们也研究无向树.所谓无向树就是 ...

  6. 数据结构-自平衡二叉查找树(AVL)详解

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

  7. 算法学习 - 平衡二叉查找树实现(AVL树)

    平衡二叉查找树 平衡二叉查找树是非常早出现的平衡树,由于全部子树的高度差不超过1,所以操作平均为O(logN). 平衡二叉查找树和BS树非常像,插入和删除操作也基本一样.可是每一个节点多了一个高度的信 ...

  8. 树的平衡之AVL树——错过文末你会后悔,信我

    学习数据结构应该是一个循序渐进的过程: 当我们学习数组时,我们要体会数组的优点:仅仅通过下标就可以访问我们要找的元素(便于查找). 此时,我们思考:假如我要在第一个元素前插入一个新元素?采用数组需要挪 ...

  9. 二叉查找树(二叉排序树)的详细实现,以及随机平衡二叉查找树Treap的分析与应用

    这是一篇两年前写的东西,自我感觉还是相当不错的Treap教程.正好期末信息科学技术概论课要求交一个论文,就把这个东西修改了一下交了,顺便也发到这里吧. 随机平衡二叉查找树Treap的分析与应用 1.序 ...

随机推荐

  1. SQL Server 创建用户

    增加角色 role_for_nc 1.exec sp_addrole 'role_for_nc'; 创建一个 SQL Server 登录名wlzx,密码为"123",默认数据库为 ...

  2. .Net程序员学习Linux最简单的方法(转载)

    有很多关于Linux的书籍.博客.大多数都会比较“粗暴“的将一大堆的命令塞给读者,从而使很多.NET程序员望而却步.未入其门就路过了. 所以我设想用一种更为平滑的学习方式, 就是在学习命令时,先用纯语 ...

  3. springboot2.x如何添加事务

    什么时候需要添加事务呢?一般情况下,如果该方法有两条SQL语句或者以上都需要添加(个人感觉:)). 首先需要在我们的启动类加上 @EnableTransactionManagement //开启事务管 ...

  4. Spring课程 Spring入门篇 3-2 Spring bean装配(上)之bean的生命周期

    课程链接: 本节主要讲了三大块内容 1 bean的生命周期概念 2 bean的初始化和销毁的三种方式对比(代码演练) 3 总结 1 bean的生命周期概念 1.1 bean的定义:xml中关于bean ...

  5. python反爬之用户代理

    # requests是第三方库,需要安装 pip install requests import requests import random # 通常很多网站都会设置检测请求头中的User-Agen ...

  6. CST,CET,UTC,GMT,DST,Unix时间戳几种常见时间概述与关系

    1.UTC: Universal Time Coordinated 协调世界时,又称世界标准时间 多数的两地时间表都以GMT来表示,但也有些两地时间表上看不到GMT字样,出现的反而是UTC这3个英文字 ...

  7. jquery-ui sortable 排序

      https://blog.csdn.net/u013066244/article/details/51954198 <link ref="stylesheet" href ...

  8. 微信公众平台开发——helloworld

    威信公众平台有两种模式:编辑模式 和 开发模式. 普通的功能可以通过编辑模式来搞定.开发模式具有更多的功能.让我们来使用开发模式开发helloword吧 步骤如下: 1.先注册一个公众号(https: ...

  9. 微信小程序之性能优化

    如果做前端仅仅停留在编码和实现业务功能上面,可能进步速度会有些慢,但是如果经历了对页面的性能优化之后而且有所成绩的话那就不同了,因为你对他背后的机制进行了研究,才能做好性能优化. 做微信小程序也是一样 ...

  10. 关于Authorware的十二种使用技巧

    Authorware是美国Macromedia公司(现已被adobe公司收购)开发的一种多媒体制作软件,它是一个图标导向式的多媒体开发工具.今天我们学习一下Authorware的十二种使用技巧,如果你 ...