本文将介绍AVL树及其插入、删除操作,最后使用C编程语言实现基于平衡因子(balance factor)的AVL树

什么是AVL树?

AVL树(AVL tree)是前苏联计算机科学家Adelson-Velsky和Landis发明的一种自平衡二叉查找树(self-balancing binary search tree)。它有两大属性,一个是继承自二叉查找树的查找属性(binary search property),另一个是AVL树特有的平衡因子属性(balance factor property)。

节点的平衡因子是节点两个子树的高度差

    BalanceFactor(N) = Height(RightSubtree(N)) – Height(LeftSubtree(N))

AVL树限定任意节点两个子树的高度差最大为1

    BalanceFactor(N) ∈ {–1,0,+1}

由于AVL树是一种二叉查找树,所以它只能维持大体平衡,无法达到完全平衡。AVL树通过限定任意节点两个子树的高度差最大为1来保证二叉查找树的大体平衡,如果高度差大于1,则需要重新平衡。

AVL树只能大体平衡,2-3-4树通过可变的元素数量可完全平衡。

       1
/ \ (1)
5 9 / \
/ (5) (6 9)
6 AVL树 2-3-4树

插入、删除操作

插入、删除操作后需要更新所有被影响的节点的平衡因子,稍作观察就能发现这些节点一定在从根节点到被插入、删除节点的路径上,这些节点都是被插入、删除节点的祖先节点(ancestors)。如何更新这些节点的平衡因子?如果更新后的平衡因子为+2或-2,如何重新平衡(rebalance)?

为了更好的描述,我们把根节点到被插入、删除节点的路径称作查找路径(search path),这条路径贯穿被插入、删除节点的所有祖先节点。

插入6的查找路径为1,9

      1
/ \
5 9 删除6的查找路径为1,9 1
/ \
5 9
/
6 所以插入、删除操作只会影响查找路径上节点的平衡因子,而不会影响别的节点的平衡因子。

AVL树的插入操作

插入操作可能会导致查找路径上节点的高度增大,所以需要更新查找路径上节点的平衡因子,如果更新平衡因子后节点违背了平衡因子属性,则需要通过旋转进行重新平衡。过程如下:

  1. 从被插入节点的父节点开始,按照查找路径原路返回直到根节点,返回过程中更新当前节点的平衡因子,如果发现当前节点更新后的平衡因子绝对值大于1,则使用旋转操作进行重新平衡;
  2. 达到以下任一条件则完成所有操作。

    a. 节点高度保持不变;

    b. 旋转操作(该节点必然恢复原高度);

    c. 到达根节点。

AVL树的删除操作

与插入操作类似,删除操作可能会导致查找路径上节点的高度减小,所以需要更新查找路径上节点的平衡因子,如果更新平衡因子后节点违背了平衡因子属性,则需要通过旋转进行重新平衡。过程如下:

  1. 从被删除节点的父节点开始,按照查找路径原路返回,返回过程中更新当前节点的平衡因子,如果发现当前节点更新后的平衡因子绝对值大于1,则使用旋转操作进行重新平衡;
  2. 达到以下任一条件则完成更新和修复操作。

    a. 节点高度保持不变;

    b. 旋转操作且旋转后节点恢复原高度;

    c. 到达根节点。

综上,AVL树的插入操作最多只需要一次旋转操作就能重新平衡,而删除操作则可能需要多次旋转操作才能重新平衡。

AVL树的实现

经过较长时间的学习和分析,使用C编程语言实现了一个完整的基于平衡因子的AVL树,源码链接为https://github.com/xieqing/avl-tree,该实现通过了较完整的测试用例的验证,README.md对AVL树的实现做了详尽的分析,另外,通过一个简单的使用示例avl_example.c,您可以快速了解它的使用方法。

欢迎大家指正。

/*
* Copyright (c) 2019 xieqing. https://github.com/xieqing
* May be freely redistributed, but copyright notice must be retained.
*/

使用C编程语言实现AVL树的更多相关文章

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

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

  2. AVL树原理及实现(C语言实现以及Java语言实现)

    欢迎探讨,如有错误敬请指正 如需转载,请注明出处http://www.cnblogs.com/nullzx/ 1. AVL定义 AVL树是一种改进版的搜索二叉树.对于一般的搜索二叉树而言,如果数据恰好 ...

  3. AVL树

    AVL树 在二叉查找树(BST)中,频繁的插入操作可能会让树的性能发生退化,因此,需要加入一些平衡操作,使树的高度达到理想的O(logn),这就是AVL树出现的背景.注意,AVL树的起名来源于两个发明 ...

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

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

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

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

  6. 数据结构图文解析之:AVL树详解及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

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

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

  8. PAT树_层序遍历叶节点、中序建树后序输出、AVL树的根、二叉树路径存在性判定、奇妙的完全二叉搜索树、最小堆路径、文件路由

    03-树1. List Leaves (25) Given a tree, you are supposed to list all the leaves in the order of top do ...

  9. 论AVL树与红黑树

    首先讲解一下AVL树: 例如,我们要输入这样一串数字,10,9,8,7,15,20这样一串数字来建立AVL树 1,首先输入10,得到一个根结点10 2,然后输入9, 得到10这个根结点一个左孩子结点9 ...

随机推荐

  1. configEnvironment()源码探究

    该方法目的是对上面刚创建的环境对象进行相关配置,包含两步:配置属性源和配置活跃profiles. 其中配置属性源如下: 1.首先获取属性源 2.然后将默认属性源添加到属性源中 3.然后将命令行属性源添 ...

  2. VSS2005源代码管理启用http方式

    一直在使用vss管理源代码,在服务器上使用文件共享当方式.最近安全形式升级,禁止使用文件共享,因此要升级到http方式. 按照网上的教程,一路前行. 1.登录服务器桌面,打开vss administr ...

  3. python模拟大数据登陆

    #针对tableu 撰写的大数据框架 #tesseract 识别简单的验证码 不多说  直接上代码 # coding:utf-8 from selenium import webdriver from ...

  4. java Base36 算法

    package com.github.linushp.wsblog.utils; import java.math.BigInteger; import java.nio.charset.Charse ...

  5. WPF-------依赖项属性

    http://www.cnblogs.com/Zhouyongh/archive/2009/09/10/1564099.html http://www.cnblogs.com/Zhouyongh/ar ...

  6. java程序中的乱码方案

    1. 万能方式,既能够解决POST请求乱码,又能够解决GET请求乱码 操作方法:先将服务器中接收到的数据采用ISO-8859-1的方式解码,回归原始状态, 再给定一种支持简体中文的编码方式重新编码组装 ...

  7. 试用 Angular v6 的 Ivy compiler

    “Ivy” 是 Angular v6 的新一代渲染器.从 v6.0.0-beta.1 开始,Ivy 已经作为体验 API 发布. 作为下一代的 Angular 的视图引擎,重点在于彻底缩减代码尺寸并增 ...

  8. redis读书笔记

    1.redis两种存储机制(持久化) Redis的存储机制分为:Snapshot和AOF 都先将内存存储在内存中. (1)Snapshot当数据累计到一定的阈值,就会触发dump将数据一次性写入到数据 ...

  9. memory_profiler的使用

    作用:memory_profiler是用来分析每行代码的内存使用情况 使用方法一: 1.在函数前添加 @profile 2.运行方式: python -m memory_profiler memory ...

  10. python爬虫爬取京东、淘宝、苏宁上华为P20购买评论

    爬虫爬取京东.淘宝.苏宁上华为P20购买评论 1.使用软件 Anaconda3 2.代码截图 三个网站代码大同小异,因此只展示一个 3.结果(部分) 京东 淘宝 苏宁 4.分析 这三个网站上的评论数据 ...