平衡二叉树(AVL)树详解

AVL树详解&面试题-判断一棵树是否是平衡二叉树 上次写了关于二叉搜索树的分析,但是二叉搜索树有一个缺陷,就是当插入一个有序(或接近有序)的序列时,二叉搜索树就相当于一个链表了,搜索效率会特别低。那么,如何来改进呢?这就引入了AVL树(高度平衡二叉树),那么下面我们一起来了解一下AVL树吧! AVL树的特征: 1、左右子树的高度差都不超过1; 2、左右子树都是AVL树; 3、每个节点都有一个平衡因子bf(blance fator ),其值为 阅读详情

1.二叉排序树可能存在的问题

给你一个数列{1,2,3,4,5,6},要求创建一颗二叉排序树(BST,如下图
在这里插入图片描述
可以看到这是二叉排序树存在许多的问题,那怎么解决呢?用平衡二叉树(AVL)来解决.

2.平衡二叉树基本介绍

(1)平衡二叉树也叫做平衡二叉搜索树(Self-balancing binary search tree)又称为AVL树,可以保证查询效率较高。
(2)具有以下特点:它是一颗空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一颗平衡二叉树。平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。
(3)举例说明,看看下面哪些是AVL树。
在这里插入图片描述

3.平衡二叉树的左旋转

(1)要求:给您一个数列,创建处对应的平衡二叉树,数列{4,3,6,5,7,8}
(2)示意图:
在这里插入图片描述
(3)代码实现:

//左旋转
public void leftRotate() {
    //1.创建新的节点,以当前根节点的值
    Node newNode = new Node(this.value);
    //2.把新节点的左子树设置为当前节点的左子树
    newNode.left = this.left;
    //3.把新节点的右子树设置成为当前节点的右子树的左子树
    newNode.right = this.left.right;
    //4.把当前节点的值换为右子节点的值
    this.value = this.right.value;
    //5.把当前节点的右子树设置成当前节点的右子树的右子树
    this.right = this.right.right;
    //6.把当前节点的左子树设置为新节点
    this.left = newNode;
}

4.平衡二叉树的右旋转

(1)要求;给你一个数列,创建对应的平衡二叉树,数列{10,12,8,9,7,6}
(2)示意图:
在这里插入图片描述
(3)代码实现

//右旋转
 public void rightRotate() {
     //1.创建一个新的节点newNode(以根节点的值10创建),创建一个新的节点,值等于当前根节点的值,new  Node(this.value)
     Node newNode = new Node(this.value);
     //2.把新节点的右子树设置了当前节点的右子树,newNode.right=this.right
     newNode.right = this.right;
     //3.把新节点的左子树设置成当前节点的左子树的右子树,newNode.left = this.left.right
     newNode.left = this.left.right;
     //4.把当前节点的值换成当前节点左子节点的值,this.value = this.left.value
     this.value = this.left.value;
     //5.把当前节点的左子树设置成当前节点的左子树的左子树,this.left = this.left.left
     this.left = this.left.left;
     //6.把当前节点的右子树设置成新节点,this.right=newNode
     this.right = newNode;
 }

5.平衡二叉树完整代码

class AvlTree {
    private Node root;

    public Node getRoot() {
        return root;
    }

    public void setRoot(Node root) {
        this.root = root;
    }

    //创建二叉排序树
    public void add(Node node) {
        if (root == null) {
            root = node;
            return;
        }
        root.addNode(node);
        //当添加完一个节点后,如果右子树的高度-左子树的高度 > 1 且当前节点的右子节点的右子树高度大于右子节点的左子树高度,则左旋转
        if (this.root.getRightHigh() - this.root.getLeftHigh() > 1 && this.root.getRight().getRightHigh() > this.root.getRight().getLeftHigh()) {
            this.root.leftRotate();
        }
        //当添加完一个节点后,如果右子树的高度-左子树的高度 > 1 且当前节点的右子节点的右子树高度大于右子节点的左子树高度,则左旋转
        if (this.root.getLeftHigh() - this.root.getRightHigh() > 1 && this.root.getLeft().getLeftHigh()> this.root.getRight().getRightHigh()) {
            this.root.rightRotate();
        }
    }

    //中序遍历
    public void infixOrder() {
        if (root != null) {
            this.root.infixOrder();
            return;
        }
        throw new NullPointerException("根节点为空");
    }
}

//二叉排序树的节点
class Node {
    private int value;
    private Node left;
    private Node right;

    public Node(int value) {
        this.value = value;
    }

    public Node() {
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public Node getLeft() {
        return left;
    }

    public void setLeft(Node left) {
        this.left = left;
    }

    public Node getRight() {
        return right;
    }

    public void setRight(Node right) {
        this.right = right;
    }

    //中序遍历
    public void infixOrder() {
        if (this.left != null) {
            this.left.infixOrder();
        }
        System.out.println(this);
        if (this.right != null) {
            this.right.infixOrder();
        }
    }

    /**
     * 向二叉排序树中添加节点
     *
     * @param node 要添加的节点
     */
    public void addNode(Node node) {
        if (node == null) {
            throw new NullPointerException("节点为空");
        }
        //判断当前节点的值是否大于添加节点
        if (this.value > node.value) {
            //判断当前节点的左子节点是否为空
            if (this.left == null) {
                this.left = node;
                return;
            }
            //递归
            this.left.addNode(node);
            return;
        }
        //判断当前节点的右子节点是否为空
        if (this.right == null) {
            this.right = node;
            return;
        }
        //递归
        this.right.addNode(node);
    }

    //返回当前节点的高度
    public int getTreeHigh() {
        return Math.max(this.left == null ? 0 : this.left.getTreeHigh(), this.right == null ? 0 : this.right.getTreeHigh()) + 1;
    }

    //返回左子树的高度
    public int getLeftHigh() {
        if (this.left == null) {
            return 0;
        }
        return this.left.getTreeHigh();
    }

    //返回右子树的高度
    public int getRightHigh() {
        if (this.right == null) {
            return 0;
        }
        return this.right.getTreeHigh();
    }

    //左旋转
    public void leftRotate() {
        //1.创建新的节点,以当前根节点的值
        Node newNode = new Node(this.value);
        //2.把新节点的左子树设置为当前节点的左子树
        newNode.left = this.left;
        //3.把新节点的右子树设置成为当前节点的右子树的左子树
        newNode.right = this.left.right;
        //4.把当前节点的值换为右子节点的值
        this.value = this.right.value;
        //5.把当前节点的右子树设置成当前节点的右子树的右子树
        this.right = this.right.right;
        //6.把当前节点的左子树设置为新节点
        this.left = newNode;
    }
   //右旋转
    public void rightRotate() {
        //1.创建一个新的节点newNode(以根节点的值10创建),创建一个新的节点,值等于当前根节点的值,new  Node(this.value)
        Node newNode = new Node(this.value);
        //2.把新节点的右子树设置了当前节点的右子树,newNode.right=this.right
        newNode.right = this.right;
        //3.把新节点的左子树设置成当前节点的左子树的右子树,newNode.left = this.left.right
        newNode.left = this.left.right;
        //4.把当前节点的值换成当前节点左子节点的值,this.value = this.left.value
        this.value = this.left.value;
        //5.把当前节点的左子树设置成当前节点的左子树的左子树,this.left = this.left.left
        this.left = this.left.left;
        //6.把当前节点的右子树设置成新节点,this.right=newNode
        this.right = newNode;
    }
    @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                '}';
    }

}

6.平衡二叉树的双旋转

前面两个数列,进行单旋转(记一次旋转)就可以将非平衡二叉树转成平衡二叉树,但是再某些情况下,单旋转不能完成平衡二叉树的转换。比如
int[] array={10,11,7,6,8,9}或者int[] array={2,1,6,5,7,3},进过一次旋转,非平衡二叉树并没有转为平衡二叉树。
问题分析:在这里插入图片描述
改进之后的代码:

public void add(Node node) {
    if (root == null) {
        root = node;
        return;
    }
    root.addNode(node);
    //当添加完一个节点后,如果右子树的高度-左子树的高度 > 1 ,则进行左旋转
    if (this.root.getRightHigh() - this.root.getLeftHigh() > 1 ) {
        //当前节点的右子节点的左子树高度大于右子节点的右子树高度,则先对当前节点的右子节点进行右旋转
        if (this.root.getRight().getRightHigh() < this.root.getRight().getLeftHigh()) {
            this.root.getRight().rightRotate();
            //然后再对当前节点进行左旋转
            this.root.leftRotate();
            return;
        }
        this.root.leftRotate();
    }
    //当添加完一个节点后,如果左子树的高度-右子树的高度 > 1 ,则进行右旋转
    if (this.root.getLeftHigh() - this.root.getRightHigh() > 1 ) {
        //当前节点的左子节点的右子树高度大于左子节点的左子树高度,则先对当前节点的左子节点进行左旋转
        if (this.root.getLeft().getLeftHigh() < this.root.getLeft().getRightHigh()) {
            this.root.getLeft().leftRotate();
            //然后再对当前节点进行右旋转
            this.root.rightRotate();
            return;
        }
        this.root.rightRotate();
    }
}
STGCN实战:从零构建PyTorch时空图卷积网络预测城市交通流 本文详细介绍了如何使用PyTorch从零构建时空图卷积网络(STGCN)进行城市交通流预测。通过将交通网络建模为图结构,并融合时间卷积与空间图卷积,STGCN能有效捕捉交通流的时空依赖性。文章提供了从数据预处理、核心模块(TimeBlock与STGCNBlock)搭建、模型训练到实战技巧的完整指南,帮助开发者快速掌握这一前沿的交通速度预测技术。 阅读详情

相关推荐

K型热电偶分度表读取方法

K型热电偶分度表读取方法

guaizaiguaizai的博客 5914

AVL树平衡旋转详解

感谢大佬!感谢大佬!概述 AVL树又叫做平衡二叉树。前言部分我也有说到,AVL树的前提是二叉排序树(BST或叫做二叉查找树)。由于在生成BST树的过程中可能会出现线型树结构,比如插入的顺序是:1, 2, 3, 4, 5, 6, 7..., n。在BST树中,比较理想的状况是每个子树的左子树和右子树的高度相等,此时搜索的时间复杂度是log(N)。可是,一旦这棵树演化成了线型树的时候,这个理想的情况...

Marcus-Bao的个人主页 5563

一文理解近红外光谱数据建模步骤的细节(细节知识总结)

上一篇文章,向入门的同志大体介绍了近红外光谱数据建模的内容,依据上文其实已经可以基本完成数据建模的工作,但是很多工作不够细致,本文便是分享其中的一些技术细节。

weixin_46207310的博客 5569

详解AVL树(平衡二叉树)

插入节点后对树进行旋转调整,分为四种情况。 1.右单旋 当一个平衡二叉树满足具有较高左子树时(如下图A),且要插入的节点插入到了较高左子树的左侧,此时进行右单旋。

水澹澹兮生烟 2万+

Orbbec-Gemini-335 深度相机 Python SDK 编译与配置全记录(Windows 环境)

本篇博客将围绕 Windows 系统下 Orbbec SDK 的 Python 配置与编译过程进行详细说明,主要使用的是官方提供的 pyorbbecsdk Python wrapper 项目以及 Orbbec SDK V2 Python Wrapper 配置指南,并记录了安装与配置过程中遇到的若干问题及解决办法。

Junseer的博客 1965

fpga进阶--时序约束

1、基础概念 1.1 建立(setup)/保持(hold)时间 上述的锁存沿会将数据保存下来,但是必须要满足一定的条件: 建立时间Tsu:在时钟有效沿之前,数据必须保持稳定的最小时间; 保持时间Th:在时钟有效沿之后,数据必须保持稳定的最小时间; 1.2 亚稳态(Metastability) 亚稳态是由于违背了触发器的建立和保持时间而产生的,设计中任何一个触发器都有特定的建立和保持时间,在时钟上升沿前后的这段时间窗口内,数据输入信号必须保持稳定。如果信号在这段时间内发生了变化,那么输...

HHH的博客 2443

平衡二叉树(AVL tree)概述

一、AVL tree基本概念AVL树前提是一种二叉排序树,其中每一个节点的左子树和右子树的高度差至多等于1。平衡因子BF(balance Factor):二叉树结点的左子树深度与右子树深度的值,AVL树上所有节点的BF只能是-1、0、1,如果二叉树上有一个节点的BF的绝对值大于1,那么这个二叉树就是不平衡的。最小不平衡子树:距离插入节点最近的,且平衡因子的绝对值大于1的结点为根的子树,被称为最小不...

qq_32164245的博客 2459

解锁PyCharm+Deepseek:本地部署AI编程超能力

在本次探索中,我们成功地在 PyCharm 中实现了 DeepSeek 的本地化部署,这一过程虽然涉及多个步骤,但每一步都为我们开启 AI 编程大门奠定了基础。从安装最新版 PyCharm,确保我们拥有一个功能强大且兼容性良好的开发环境,到注册 DeepSeek 账号并获取 API Key,这是连接我们与强大 AI 能力的关键纽带。接着,在 PyCharm 中安装 Continue 插件并进行精细配置,让 DeepSeek 能够深度融入我们的编程流程。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 5550

实现平衡二叉树(AVL树)的旋转

平衡二叉树也叫平衡二叉搜索树(Self-balancing binary search tree)又被称为 AVL 树, 可以保证查询效率较高。

qq_64431576的博客 1630

Matplotlib之bar3d画3D柱状图

3D柱状图通常用于展示数据集中不同分类项的数据大小或数量。与普通的柱状图相比,3D柱状图更适合展示数据的三个维度 3D 柱状图 按行/列涂颜色 柱加阴影、描黑边 自定义座标轴名、刻度标签、范围

我走的每一步都算数 1123

基于STM32L4XX、HAL库的AD7768BSTZ 模数转换器ADC驱动程序设计

/ 默认SPI配置。// 读取通道数据命令。// 通过SYNC_IN引脚触发转换(如果使用)// 处理数据...// 或者通过SPI命令。// 初始化AD7768。// SPI1引脚配置。

zhusl6688的博客 462

平衡二叉树AVL树

平衡二叉树(AVL树) 定义: AVL树是一颗特殊的二叉查找树,它具有保持平衡要求的特性,AVL树的每一个节点的左子树和右子树的高度差要求最大为1,如果超过1将破坏平衡特性,将不再是一颗平衡二叉树。 平衡条件的维持: 为什么需要维持平衡: AVL树需要时刻保持其平衡的特性,但这样的特性可能会在插入和删除的同时被打破,插入和删除新的节点造成的高度变化可能会使某些节点的左右子树的高度差超过1,所以我们需要在插入和删除的同时维护AVL树的平衡特性。 讨论如何维持AVL树的平衡: 明确平衡被破坏的位置 在讨论AV

weixin_45863060的博客 1837

蓝桥杯第七届省赛试题--“模拟风扇控制系统”

题目要求 功能简述 “模拟风扇控制系统”能够模拟电风扇工作,通过按键控制风扇的转动速度和定时时间,数码管实时显示风扇的工作模式,动态倒计时显示剩余的定时时间,系统主要由数码管显示、单片机最小系统、按键输入和电机控制保护电路组成,系统框图如图 1 所示: 单总线驱动程序、CT107D 单片机考试平台电路原理图以及本题所涉及到的芯片数据手册,可参考计算机上的电子文档。程序流程图及相关工程文件请以考生...

qq_43280087的博客 2659

AVL树(平衡二叉树,旋转树)详解

AVL树(平衡二叉树): AVL树,又叫旋转树。   AVL树本质上是一颗二叉查找树,但是它又具有以下特点:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为平衡二叉树。下面是平衡二叉树和非平衡二叉树对比的例图: 平衡因子(bf):结点的左子树的深度减去右子树的深度,那么显然-1<=b...

qq_43096062的博客 1567

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

数据结构:AVL树详解(平衡二叉树)

假如以 parent 为根的子树不平衡,即 parent 的平衡因子为2或者-2,分以下情况考虑parent的平衡因子为2,说明parent的右子树高,设parent的右子树的根为subR当subR的平衡因子为1时,执行左单旋当subR的平衡因子为-1时,执行右左双旋parent的平衡因子为-2,说明parent的左子树高,设parent的左子树的根为subL当subL的平衡因子为-1是,执行右单旋当subL的平衡因子为1时,执行左右双旋。

机会是给有准备的人 6314

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

查找算法【平衡二叉树】 - 原理 AVL树详解

查找算法【平衡二叉树】 - 原理 AVL树详解

代码改变世界 776

详解平衡二叉树(AVL树)以及Python实现相关操作

平衡二叉树1、概述2、定义3、失衡二叉排序树的分析与调整3.1 左旋转3.2 右旋转 1、概述 为什么引入平衡二叉树? \quad \quad含有n个结点的二叉排序树的平均查找长度ASL和树的形态有关 问题: 如何提高形态不均衡的二叉排序树的查找效率? 解决办法: 做平衡化处理,尽量让二叉树的形状均衡,转换成平衡二叉树。 2、定义 平衡二叉树(balanced binary tree) 又称AVL树(Adelson - VelskII and Landis)。 一棵平衡二叉树或者是空树,或者是具有

weixin_45666566的博客 3608

二叉查找树及平衡二叉树(AVL树)详解

本文包括二叉查找树以及AVL树的详解及案例

一个人漫不经心的博客 1467

平衡二叉树(AVL树)原理详解从理论到实现的全面解析

平衡因子是AVL树实现平衡的核心概念。对于树中的任意一个节点,其平衡因子定义为它的左子树高度减去它的右子树高度。根据AVL树的定义,所有节点的平衡因子只能取-1、0或1这三个值。如果某个节点的平衡因子的绝对值大于1,则表示该节点处于不平衡状态,需要通过旋转操作来恢复平衡。计算节点的高度通常采用递归方式,空节点(null)的高度定义为-1,叶子节点的高度定义为0。

u011779969的博客 469

数据结构-平衡二叉树之一AVL树详解

1.

tiankong_的博客 1687

平衡二叉树(AVL树)核心原理与调整策略详解

上,可以直接体验我配置好的平衡二叉树可视化项目,无需搭建环境就能实时观察各种操作下的树结构调整过程。平台自动生成的演示界面非常直观,特别适合用来验证不同旋转场景下的算法行为。平衡二叉树(AVL树)通过高度平衡的约束,保证了二叉搜索树的最优查询效率。:演示了6种删除场景(左右子树各3种),通过动画分步展示旋转过程。:针对被破坏节点,比较其较高子树的孩子节点高度。插入频繁场景可考虑红黑树(近似平衡)需要递归检查所有祖先节点的平衡性。特点:只需一次旋转即可恢复平衡。混合路径则对应LR或RL型。

ThunderstormFalcon78的博客 716

平衡二叉树(AVL树)介绍及实现代码详解

平衡二叉树,又称AVL树,是一种自平衡的二叉搜索树。通过保持平衡,AVL树可以确保在最坏情况下的查找、插入和删除操作的时间复杂度为O(log n)。

jack黄从零学c++的博客 627

平衡二叉树(AVL树的定义,旋转详解)

平衡二叉树:或者是一棵空树,或是具有下列性质的二叉树:它的左子树和右子数都是平衡二叉树,且左子树和右子树的深度之差的绝对值不超过1 结点的平衡因子BF:该结点的左子树的深度减去它的右子树的深度,则平衡二叉树上所有结点的平衡因子只能是-1,0,1. 那如何使二叉排序树变为平衡二叉树呢?通过各种旋转 LL顺时针,RR逆时针,LR:先RR再LL,RL:先LL再RR 什么时候需要单旋转,而什么时候...

wu可达的博客 1787

avl树 java_平衡二叉树 AVL树结构详解 [Java实现]

作者NeroJings来源https://blog.youkuaiyun.com/zhang6622056/article/details/82698859本文思维导图简述先不说平衡二叉树,我们单开来说,这样比较方便理解。先说二叉树,再说平衡条件,没那么多花里胡哨的理论,我只是想让大家看完能明白,能写出来。二叉树什么是二叉树?二叉树数据结构,顾名思义,只有两个叉,在数据结构中,操作性能要远高于线性结构,有O(...

weixin_34116482的博客 120

平衡二叉树(AVL树)详解:Java实现与旋转操作全解析

T key;int height;// 节点高度,用于平衡计算// 新节点高度初始化为1AVL树通过严格的平衡条件和四种旋转机制,完美解决了二叉搜索树的退化问题。掌握其核心思想,不仅能提升数据结构理论水平,更能为理解现代数据库和编程语言的底层实现打下坚实基础。提示:在实际开发中,Java的TreeMap和C++的std::map使用的是红黑树而非AVL树,因为红黑树的旋转次数更少,更适合频繁插入删除的场景。但AVL树在查找密集型应用中仍有不可替代的优势。

qq_54076831的博客 905

【数据结构】平衡二叉树(AVL树)详解

平衡二叉树,又称AVL树。是一种高度平衡的二叉排序树。这里的”高度“ 大家理解为 height。也就是节点的左子树和右子树的高度差绝对值不超过1。 重点一:高度平衡 指的是 节点 左子树高 与 右子树高,差值绝对值不超过1。 重点二:AVL的插入函数 先按照二叉树原理插入节点,然后再看当前树是否平衡。   ******* 一定要自己写一遍 ,重点看插入函数********   ht...

延龙的博客 1403

平衡二叉树(AVL)插入、删除详解——基于树的查找(二)

由上节内容二叉排序树可知: 二叉排序树在最好的情况下只需O(logn)的时间代价; 但在最差情况下会蜕化为线性查找的时间复杂度O(n); 造成原因:这种情况主要是由于二叉排序树中结点分布不均衡导致,可能是二叉排序树在建立时由于输入序列造成的,也可能是由于在树中不断插入结点而造成的。 解决想法:如果能够找到一种方法,使得二叉排序树不受输入序列或插入结点等的影响,...

weixin_39651041的博客 1965
上一篇: 二叉排序树(BST)的创建和删除
下一篇: (B树、B+树和B*树)多路查找树详解
suixinghero
博客等级 码龄7年 10粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值