AVL树-自平衡的二叉搜索树

本文图片来源:手把手教,手写AVL树 - 不止是编程 - 博客园

AVL树的概念

自平衡

当二叉搜索树处于平衡状态的时候,其操作时间复杂度为O(logN),但当二叉搜索树是单支树的时候,其搜索效率则为O(N)。可见,二叉搜索树的平衡性是影响其操作效率的关键。
由此出发,学者们设计了第一个平衡二叉搜索树,即AVL树。AVL树作为第一个平衡的二叉搜索树,其影响非常深远,后来的很多平衡结构都借鉴了AVL树的设计思想。

AVL树的定义

一棵AVL树或者是空树,或者是具有下列性质的二叉搜索树:

  • 它的左子树和右子树都是AVL树。
  • 左子树和右子树的高度之差的绝对值不超过1

要注意,AVL的平衡性是一种相对的平衡,并非一种绝对的平衡。它不要求左子树和右子树的高度绝对相等,而仅仅是左子树和右子树的高度之差的绝对值不超过1即可。因为绝对的平衡难以实现。

如果给AVL树中的每一个节点都附加一个数字,该数字指示该节点右子树的高度减去左子树的高度所得的高度差,那么这个数字即为该节点的平衡因子。根据AVL树的定义,任一节点的平衡因子只能取-1、0或1。

AVL树的旋转

在一个平衡的二叉搜索树中插入一个新节点,就会造成其失衡,需要从插入位置沿通向根的路径回溯,检查各节点的平衡因子,在某一节点发现高度不平衡,则停止回溯。然后从发生不平衡的节点起,往下取三层,可以归纳为四种情况:

  1. 向某节点的左子树中插入一个左孩子。
  2. 向某节点的右子树中插入一个右孩子。
  3. 向某节点的左子树中插入一个右孩子。
  4. 向某节点的右子树中插入一个左孩子。

对应的处理方式:

单旋

  1. 右旋操作

以中间节点为轴,进行顺时针旋转,该中间节点的原父节点将变成该节点的右子节点,该中间节点的右子树则变成其原父节点的左子树。
基本情况

复杂情况

  1. 左旋操作

对应的,左旋的方法是以三个呈直线排列的节点的中间节点为轴,进行逆时针旋转。该中间节点的原父节点将变成该节点的左子节点,该中间节点的左子树则变成其原父节点的右子树

双旋

  1. 先左后右双旋转

以3个成折线排列的节点中的末节点为轴,进行逆时针旋转。使末节点代替中间节点的位置,也就是让末节点成为原中间节点的父节点,这时,三个节点将成一直线排列,再以新的中间节点为旋转轴做右旋操作,即可完成平衡化操作。

基本情况

复杂情况

  1. 先右后左双旋转

以3个成折线排列的节点中的中间节点为轴,进行顺时针旋转。使末节点代替中间节点的位置,也就是让末节点成为原中间节点的父节点,这时,三个节点将成一直线排列,再以新的中间节点为旋转轴做左旋操作,即可完成平衡化操作。

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/avl%e6%a0%91-%e8%87%aa%e5%b9%b3%e8%a1%a1%e7%9a%84%e4%ba%8c%e5%8f%89%e6%90%9c%e7%b4%a2%e6%a0%91/

(0)
彭晨涛彭晨涛管理者
上一篇 2019年11月24日
下一篇 2019年11月26日

相关推荐

  • leetcode173-二叉搜索树迭代器

    原题 实现一个二叉搜索树迭代器。你将使用二叉搜索树的根节点初始化迭代器。 调用 next() 将返回二叉搜索树中的下一个最小的数。 示例: BSTIterator iterator…

    2020年1月16日
    060
  • 拉帮结派的数据结构-并查集

    本文参考资源: 超超有爱爱-----并查集~~~chen_zan_yu的博客-CSDN博客 概述 并查集通常用作集合的合并。 并查集是一种树形结构,又叫“不相交集合”,保持了一组不…

    2020年2月17日
    0140
  • 算法竞赛常用数据结构-字典树Trie

    本文参考资源: 详谈树结构(传统树、字典树、hash 树、Merkle Patricia Tree)_C/C++_smilejiasmile的博客-CSDN博客 概述 Tire树称…

    2020年2月17日
    0660
  • Java基础查缺补漏03(附赠哈夫曼树&哈夫曼编码)

    继续我的复习刷题 构造器显式调用父类构造方法的规则 题目: 以下程序的输出结果为 class Base{ public Base(String s){ System.out.pri…

    2020年5月27日
    0220
  • 弱平衡的二叉查找树-红黑树

    为什么会出现红黑树? 之前我们提过AVL树-自平衡的二叉搜索树,但是一旦树的节点发生变化,AVL树为了维持绝对平衡(虽然说AVL也容忍左右两个子树最多为1的高度差,但这里仍视为绝对…

    2020年2月9日
    01000
  • leetcode622-设计循环队列

    设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。 循环队列的一个好处是…

    算法 2019年11月24日
    0130
  • 带有优先级的完全二叉树-堆

    堆的概念 堆是一种完全二叉树(除了最后一层每个节点的子节点都是满的,最后一层的节点也是集中在左边) 虽然堆是一棵二叉树,但也由于它是一棵完全二叉树的原因,可以使用一个数组来表示堆。…

    算法 2020年2月9日
    0180
  • leetcode707-设计链表

    原题 设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用…

    算法 2019年12月14日
    0290
  • 海量数据算法-BitMap介绍和实现

    作为一个有素质的程序员,在面试中(不是) 难免会遇到海量数据相关的问题,之前有注意过java.util下面有一个BitSet数据结构,但不是很明白是做什么用的。今天就来研究一下它背…

    算法 2020年2月27日
    03490
  • 多叉平衡查找树-B树与B+树

    本文参考链接: 从B树、B+树、B*树谈到R 树_磁盘,数据结构,存储_结构之法 算法之道-CSDN博客 【数据结构】B树、B+树详解 - Assassinの - 博客园 BTre…

    2020年2月8日
    0160

发表回复

登录后才能评论