基本概念

AVL树:树中任何节点的两个子树的高度最大差别为1。

AVL树的查找、插入和删除在平均和最坏情况下都是O(logn)。

AVL实现

AVL树的节点包括的几个组成对象:
(01) key -- 是关键字,是用来对AVL树的节点进行排序的。
(02) left -- 是左孩子。
(03) right -- 是右孩子。
(04) height -- 是高度。即空的二叉树的高度是0,非空树的高度等于它的最大层次(根的层次为1,根的子节点为第2层,依次类推)。

AVL旋转算法

AVL失衡四种形态:

LL(根的左子树的左子树高):根节点的左子树的左子树还有非空子节点,导致"根的左子树的高度"比"根的右子树的高度"大2。

LR(根的左子树的右子树高):根节点的左子树的右子树还有非空子节点,导致"根的左子树的高度"比"根的右子树的高度"大2。

RL(根的右子树的左子树高):根节点的右子树的左子树还有非空子节点,导致"根的右子树的高度"比"根的左子树的高度"大2。

RR(根的右子树的右子树高):根节点的右子树的右子树还有非空子节点,导致"根的右子树的高度"比"根的左子树的高度"大2。

旋转算法实现

1 LL(一步到位)

LL失去平衡的情况,可以通过一次旋转让AVL树恢复平衡。如下图:

图中左边是旋转之前的树,右边是旋转之后的树。从中可以发现,旋转之后的树又变成了AVL树,而且该旋转只需要一次即可完成。
对于LL旋转,你可以这样理解为:LL旋转是围绕"失去平衡的AVL根节点"进行的,也就是节点k2;而且由于是LL情况,即左左情况,就用手抓着"左孩子,即k1"使劲摇。将k1变成根节点,k2变成k1的右子树,"k1的右子树"变成"k2的左子树"。

/*
* LL:左左对应的情况(左单旋转)。
*
* 返回值:旋转后的根节点
*/
static Node* left_left_rotation(AVLTree k2)
{
    AVLTree k1;

    k1 = k2->left;
    k2->left = k1->right;
    k1->right = k2;

    k2->height = MAX( HEIGHT(k2->left), HEIGHT(k2->right)) + 1;
    k1->height = MAX( HEIGHT(k1->left), k2->height) + 1;

    return k1;
}

2 RR(一步到位)

理解了LL之后,RR就相当容易理解了。RR是与LL对称的情况!RR恢复平衡的旋转方法如下:

图中左边是旋转之前的树,右边是旋转之后的树。RR旋转也只需要一次即可完成。

/*
* RR:右右对应的情况(右单旋转)。
*
* 返回值:旋转后的根节点
*/
static Node* right_right_rotation(AVLTree k1)
{
    AVLTree k2;

    k2 = k1->right;
    k1->right = k2->left;
    k2->left = k1;

    k1->height = MAX( HEIGHT(k1->left), HEIGHT(k1->right)) + 1;
    k2->height = MAX( HEIGHT(k2->right), k1->height) + 1;

    return k2;
}

3 LR(两步旋转RR->LL)

LR失去平衡的情况,需要经过两次旋转才能让AVL树恢复平衡。如下图:


第一次旋转是围绕"k1"进行的"RR旋转",第二次是围绕"k3"进行的"LL旋转"。

/*
* LR:左右对应的情况(左双旋转)。
*
* 返回值:旋转后的根节点
*/
static Node* left_right_rotation(AVLTree k3)
{
    k3->left = right_right_rotation(k3->left);

    return left_left_rotation(k3);
}

4 RL(两步旋转LL->RR)

RL是与LR的对称情况!RL恢复平衡的旋转方法如下:

第一次旋转是围绕"k3"进行的"LL旋转",第二次是围绕"k1"进行的"RR旋转"。

/*
* RL:右左对应的情况(右双旋转)。
*
* 返回值:旋转后的根节点
*/
static Node* right_left_rotation(AVLTree k1)
{
    k1->right = left_left_rotation(k1->right);

    return right_right_rotation(k1);
}

 

AVL操作

插入

步骤1:递归插入到左子树或右子树(left<root<right);

步骤2:比较左右子树高度来确定AVL失衡处理类型:

插入到左子树,就有LL和LR:通过left<root<right确定;

插入到右子树,就有RL和RR:通过left<root<right确定;

步骤3:修正树高。

删除

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

  1. Algorithms: 二叉平衡树(AVL)

    二叉平衡树(AVL):   这个数据结构我在三月份学数据结构结构的时候遇到过.但当时没调通.也就没写下来.前几天要用的时候给调好了!详细AVL是什么,我就不介绍了,维基百科都有.  后面两月又要忙了. ...

  2. 树-二叉搜索树-AVL树

    树-二叉搜索树-AVL树 树 树的基本概念 节点的度:节点的儿子数 树的度:Max{节点的度} 节点的高度:节点到各叶节点的最大路径长度 树的高度:根节点的高度 节点的深度(层数):根节点到该节点的路 ...

  3. AVL树(二叉平衡树)详解与实现

    AVL树概念 前面学习二叉查找树和二叉树的各种遍历,但是其查找效率不稳定(斜树),而二叉平衡树的用途更多.查找相比稳定很多.(欢迎关注数据结构专栏) AVL树是带有平衡条件的二叉查找树.这个平衡条件必 ...

  4. 二叉平衡树AVL的插入与删除(java实现)

    二叉平衡树 全图基础解释参考链接:http://btechsmartclass.com/data_structures/avl-trees.html 二叉平衡树:https://www.cnblogs ...

  5. (4) 二叉平衡树, AVL树

    1.为什么要有平衡二叉树? 上一节我们讲了一般的二叉查找树, 其期望深度为O(log2n), 其各操作的时间复杂度O(log2n)同时也是由此决定的.但是在某些情况下(如在插入的序列是有序的时候), ...

  6. java项目---用java实现二叉平衡树(AVL树)并打印结果(详)(3星)

    package Demo; public class AVLtree { private Node root; //首先定义根节点 private static class Node{ //定义Nod ...

  7. 从零开始学算法---二叉平衡树(AVL树)

    先来了解一些基本概念: 1)什么是二叉平衡树? 之前我们了解过二叉查找树,我们说通常来讲, 对于一棵有n个节点的二叉查找树,查询一个节点的时间复杂度为log以2为底的N的对数. 通常来讲是这样的, 但 ...

  8. 各种查找算法的选用分析(顺序查找、二分查找、二叉平衡树、B树、红黑树、B+树)

    目录 顺序查找 二分查找 二叉平衡树 B树 红黑树 B+树 参考文档 顺序查找 给你一组数,最自然的效率最低的查找算法是顺序查找--从头到尾挨个挨个遍历查找,它的时间复杂度为O(n). 二分查找 而另 ...

  9. 看动画学算法之:平衡二叉搜索树AVL Tree

    目录 简介 AVL的特性 AVL的构建 AVL的搜索 AVL的插入 AVL的删除 简介 平衡二叉搜索树是一种特殊的二叉搜索树.为什么会有平衡二叉搜索树呢? 考虑一下二叉搜索树的特殊情况,如果一个二叉搜 ...

随机推荐

  1. hdu 3631

    最短路  执行一遍 Floyd算法    比赛的时候没有想到, 用了优化的Dijkstra  超时到死 #include <cstdio> #include <cstring> ...

  2. unity3d与eclipse协同工作环境

    原地址:http://bbs.9ria.com/thread-212576-1-1.html 这个过程非常复杂.步骤一定要谨记 1,建立一个unity3d工程,然后自己丢点模型进去吧.然后设置导出时候 ...

  3. Java 内存结构备忘录

    本文详细描述了 Java 堆内存模型,垃圾回收算法以及处理内存泄露的最佳方案,并辅之以图表,希望能对理解 Java 内存结构有所帮助.原文作者 Sumith Puri,本文系 OneAPM 工程师编译 ...

  4. ECSHOP报错误Deprecated: preg_replace(): The /e modifier is depr

    http://www.ecshoptemplate.com/article-1850.html

  5. DJANGO技巧两则:模拟MKDIR -P及配合NGINX上传大文件不使超时

    这都是在开发当哪遇到的问题,网上转转,作个记录: http://blog.chinaunix.net/uid-25525723-id-1596574.html http://bookshadow.co ...

  6. 在ECLIPSE中用MAVEN和TOMCAT来建立WEBAPP

    找了很多示例,结合以下两个URL,比较简单的测试了一下. http://blog.csdn.net/clj198606061111/article/details/20221133 http://ww ...

  7. html10个特效(转载)

    http://www.html5tricks.com/10-html5-jquery-image-animatin.html 现在网页上的图片已经不再是10几年前那种低像素的静态图片了,有了HTML5 ...

  8. 214. Shortest Palindrome

    题目: Given a string S, you are allowed to convert it to a palindrome by adding characters in front of ...

  9. python脚本实例002- 利用requests库实现应用登录

    #! /usr/bin/python # coding:utf-8 #导入requests库 import requests #获取会话 s = requests.session() #创建登录数据 ...

  10. C# 调用WebService的方法

    很少用C#动态的去调用Web Service,一般都是通过添加引用的方式,这样的话是自动成了代理,那么动态代理调用就是我们通过代码去调用这个WSDL,然后自己去生成客户端代理.更多的内容可以看下面的两 ...