AVL树的实现(Java版)

AVL树的非递归实现(Java版) AVL树的非递归实现(Java版) AVL树是一种二叉查找树的改进算法,它避免了普通二叉树可能出现的长链现象,其根本的算法思想是每当对树进行插入和删除操作时,通过有限的指针变换,改变原有的树的结构,使得每个节点的左子树和右子树相对平衡。 虽然现实中AVL树算法被许多更优秀的算法所替代,但是这一套算法非常适合初学者进行练习,详细的AVL树的教程和博客不难找到。通常,AVL树是通过递归方式来实现的,这... 阅读详情

当我们用普通二叉搜索树查询数据的时候,最好情况是这是一棵平衡二叉树,时间复杂度可以达到O(log₂n);最坏情况是数据全是升序或全是降序的情况,时间复杂度会达到O(n)。为了避免这种情况,我们引入了AVL树,它在二叉搜索树的基础上通过旋转操作来保持平衡,使得所有节点的左右子树高度差的绝对值不超过1。

具体思路如图

具体代码如下

//自己创建AVL树
public class AVL {
    static class TreeNode{
        public int val;
        public int bf;
        public TreeNode left;
        public TreeNode right;
        public TreeNode parent;
        public TreeNode(int val){
            this.val = val;
        }
    }
    public TreeNode root;
    public boolean insert(int val){
        TreeNode treeNode=new TreeNode(val);
        //先正常插入
        if(root==null){
            root=treeNode;
            return true;
        }
        //正常插入的时候定义了两个新变量,应该是p(parent),一个是cur
        TreeNode p=null;
        TreeNode cur=root;
        while(cur!=null){
          if (val>cur.val){
              p=cur;
              cur=cur.right;
          } else if (val==cur.val) {
              return false;
          } else {
              p=cur;
              cur=cur.left;
          }
        }
        //走完这里之后p走到了我们要放的地方的父亲节点,cur走到了空
        if (val>p.val){
            p.right=treeNode;
        }else {
            p.left=treeNode;
        }
        treeNode.parent=p;
        cur=treeNode;
        //插入完之后,要判断是否平衡,如果不平衡,要进行旋转
        while (p!=null){
           //先增加bf,然后再判断,最后再旋转
           if(cur==p.left){
               p.bf--;
           }else {
               p.bf++;
           }
           //开始判断平衡因子是否需要旋转
            if(p.bf==0){
                break;
            } else if (p.bf==1||p.bf==-1) {
                cur=p;
                p=cur.parent;
            } else {
                //这里是p的bf等于2或者-2,是需要调整的
                if(p.bf==-2){
                    if (cur.bf==-1){
                        //我们需要右旋
                        RotateR(p);
                    }else {
                        //我们需要先左旋,再右旋
                        RotateLR(p);
                    }
                }else {
                    //p.bf==2
                    if (cur.bf==1) {
                        //我们需要左旋
                        RotateL(p);
                    }else {
                        //我们需要先右旋,再左旋
                        RotateRL(p);
                    }
                }
                break;
            }
        }
        return true;
    }

    private void RotateRL(TreeNode p) {
        TreeNode subR=p.right;
        TreeNode subRL=subR.left;
        int bf= subRL.bf;
        RotateR(p.right);
        RotateL(p);
        //重新调整bf
        if (bf==-1){
            subR.bf=0;
            p.bf=0;
            subRL.bf=1;
        }else if (bf==1){
            subR.bf=-1;
            p.bf=0;
            subRL.bf=0;
        }
    }

    private void RotateL(TreeNode p) {
        TreeNode subR=p.right;
        TreeNode subRL=subR.left;
        subR.left=p;
        p.right=subRL;
        //开始指向父亲节点
        if (subRL!=null){
            subRL.parent=p;
        }
        p.parent=subR;
        TreeNode Pp=p.parent;
        if(p==root) {
            root = subR;
            subR.parent = null;
        }else {
            if(Pp.left==p){
                Pp.left=subR;
            }else {
                Pp.right=subR;
            }
            subR.parent=Pp;
        }
        //修改bf
        p.bf=0;
        subR.bf=0;
    }

    private void RotateLR(TreeNode p) {
        TreeNode subL=p.left;
        TreeNode subLR=subL.right;
        int bf= subLR.bf;
        //我们传入的这个参数都是要转的那一部分的头节点
        RotateL(subL);
        RotateR(p);
        //重新调整bf
        if (bf==-1){
            subLR.bf=0;
            subL.bf=0;
            p.bf=1;
        }else if (bf==1){
            subLR.bf=0;
            subL.bf=-1;
            p.bf=0;
        }
    }

    //右旋
    private void RotateR(TreeNode p) {
        TreeNode subL=p.left;
        TreeNode subLR=subL.right;
        //subLR可能是空的
        //开始旋转
        //先指向子结点
        subL.right=p;
        p.left=subLR;
        //再指向父结点
        if(subLR!=null){
            subLR.parent=p;
        }
        TreeNode Pp=p.parent;
        p.parent=subL;
        //可能原来的p节点并不是根结点
        if(p==root){
            root=subL;
            subL.parent=null;
        }else {
            if (Pp.left==p){
                Pp.left=subL;
            }else {
                Pp.right=subL;
            }
            subL.parent=Pp;
        }
        //调节平衡因子,根据我给的例子来看,可以对比一下旋转完的两张图,变了p.bg和subL.bf
        p.bf=0;
        subL.bf=0;
    }
    private int height(TreeNode root) {
        if(root == null) return 0;
        int leftH = height(root.left);
        int rightH = height(root.right);

        return leftH > rightH ? leftH+1 : rightH+1;
    }

    public boolean isBalanced(TreeNode root) {
        if(root == null) return true;
        int leftH = height(root.left);
        int rightH = height(root.right);

        if(rightH-leftH != root.bf) {
            System.out.println("这个节点:"+root.val+" 平衡因子异常");
            return false;
        }

        return Math.abs(leftH-rightH) <= 1
                && isBalanced(root.left)
                && isBalanced(root.right);
    }
}
public class test {
    public static void main(String[] args) {
            int[] array = {4, 2, 6, 1, 3, 5, 15, 7, 16};
            //int[] array = {30,20,90,60,180,40};
            AVL avlTree = new AVL();
            for (int i = 0; i < array.length; i++) {
                avlTree.insert(array[i]);
            }
            System.out.println(avlTree.isBalanced(avlTree.root));

    }
}

【Gazebo安装指南】Ubuntu22.04LTS环境下的高效配置与常见问题解决 本文提供了在Ubuntu 22.04 LTS系统上高效安装和配置Gazebo仿真环境的详细指南。针对Gazebo Classic版本,文章对比了通过ROS 2仓库和Ubuntu官方仓库两种主流安装方法,并重点解决了安装过程中常见的软件包定位、模型下载及图形驱动等问题,帮助用户快速搭建稳定的机器人仿真开发环境。 阅读详情

相关推荐

大数据实战:Python与MySQL在足球赔率分析中的高效应用

本文详细介绍了如何利用Python与MySQL进行大数据实战,实现足球赔率的高效分析。通过对比Excel处理的局限性,阐述了数据库在处理百万级数据时的速度优势。文章提供了从环境搭建、使用pymysql连接数据库、利用pandas进行数据清洗与分析,到构建自动化分析系统的完整流程,旨在帮助读者将大数据技术应用于实际业务场景,显著提升数据处理与洞察效率。

weixin_29080843的博客 448

Java实现AVL树的判定问题(改编版)

Java实现AVL树的判定问题

qq_52434831的博客 368

ARTIX-7 GTP 3G-SDI 工程构建与调试实战

本文详细介绍了基于ARTIX-7 FPGA和GTP收发器的3G-SDI工程构建与调试实战。从基础概念解析到Vivado工程创建、GTP IP核配置、SDI IP核集成,再到系统集成与时钟域处理,提供了全面的技术指导。文章还分享了调试技巧、常见问题排查方法以及性能验证步骤,帮助开发者快速掌握3G-SDI视频传输技术的实现与优化。

weixin_30443813的博客 256

AVL树详解:从平衡因子到四种旋转,完整实现插入与删除

平衡二叉树是保障查找效率的关键数据结构,AVL树通过平衡因子约束左右子树高度差不超过1,避免了二叉搜索树在有序数据下退化为链表的问题,使插入、删除、查找的时间复杂度稳定在O(log n)。理解AVL树的核心在于掌握平衡因子的计算与LL、RR、LR、RL四种旋转的触发条件,本文深入剖析旋转原理与判断口诀,并给出完整的Java实现,覆盖插入、删除及高度更新等易错细节。同时,结合红黑树的性能对比,梳理AVL树在缓存索引、内存数据库等读多写少场景中的实际价值,帮助学习者在备考和面试中快速建立平衡二叉树的系统认知。

weixin_42531886的博客 307

01 ArcGIS空间分析--水文分析--利用水文分析方法提取山谷山脊线

ArcGIS空间分析的一个特别好的分析教程是汤国安老师的空间分析的内容。 实例与练习 练习1. 利用水文分析方法提取山脊、山谷线 1. 背景:山脊线、山谷线是地形特征线,它们对地形、地貌具有一定的控制作用。它们与山顶点、谷底点以及鞍部点等一起构成了地形及其起伏变化的骨架结构。因此在数字地形分析中,山脊线和山谷线以及

Meditation 1万+

io_uring vs epoll ,谁在网络编程领域更胜一筹?

简介:从定量分析的角度,通过量化 io_uring 和 epoll 两种编程框架下的相关操作的耗时,来分析二者的性能差异。 本文作者:王小光,「高性能存储技术SIG」核心成员。 背景 io_uring 在传统存储 io 场景已经证明其价值,但 io_uring 不仅支持传统存储 io,也支持网络 io。io_uring 社区有众多的开发者尝试将 io_uring 用于网络应用。我们之前也在《你认为 io_uring 只适用于存储 IO?大错特错!》中也探索过 io_uring 在网络场景的应用及其

阿里云云栖号 3035

AVL树

AVL树的性质 AVL树(Balanced Binary Tree or Height-Balanced Tree) AVL树或者是空二叉树,或者是具有如下性质的BST: 根结点的左、右子树高度之差的绝对值不超过1 且根结点左子树和右子树仍然是AVL树。 结点的平衡因子BF(Balanced Factor) 一个结点的左子树与右子树的高度之差。 AVL树中的任意结点的BF只可能是-1,0和1。 AVL树的ASL可保持在O(log2n) 在AVL树在结点高度上采用相对平衡的策略,使其平均性能接近于B

qq_41784749的博客 1万+

ESD放电路径分析

当金属外壳接地情况下,大部分外部干扰信号将会通过外壳,外壳到接地点,再由接地点回到干扰信号的地,实现干扰信号的回流,这点不仅仅适用于​ESD,对于其他的RI类干扰,也同样适合。发现内部金属板跟外壳的搭接处存在较多的缝隙点,该缝隙点对于频率较高的信号能够实现较为理想的回流,但是对于频率没有那么高的信号,则较难以实现回流,我们尝试将这些缝隙用铜箔包裹住,充分降低该金属板跟外壳的接触阻抗​。我们分析,路径3其实是不期望的路径,我们最期望的路径是1,或者2的内部金属部件跟外壳良好接触情况下的路径。

domen_pan的博客 2232

AVL树(Java)

目录一、什么是AVL树二、AVL树的实现AVL树的节点AVL树的插入AVL树的旋转右单旋左单旋左右双旋 右左双旋AVL树的验证三、AVL树的性能分析在了解什么是AVL树之前,我们先回顾二叉搜索树的概念二叉搜索树(二叉排序树),它或是一棵空树,或具有以下性质:根据二叉搜索树的性质,我们可以发现:1. 二叉搜索树中最左侧的节点是树中最小的节点,最右侧的节点是树中最大的节点2. 若采用中序遍历二叉搜索树,则可得到一个有序的序列二叉搜索树最主要的作用就是用于进行查询:当二叉搜索树是一颗完全二叉树时:其查询的平均查找

2301_76161469的博客 3185

毕设帮扶:从0到1搭建基于YOLOv5的打架斗殴检测系统——助你搞定深度学习毕设

做完这个毕设,你已经掌握了从数据准备到模型部署、界面开发的全流程。把模型部署到边缘设备(如安防摄像头的嵌入式系统)上,实现本地化实时检测与报警;加入行为严重程度分析(如轻微推搡 vs 严重斗殴)、涉事人员数量统计,让系统从“检测”升级为“智能安防决策”;尝试融合声音、红外等多模态数据,打造全方位的暴力事件监测系统。按照这个教程一步步做,你的毕设肯定能做得很扎实。要是过程中遇到啥问题,别担心,慢慢梳理或者咱们一起聊聊,一定能把这个毕设做成你满意的作品。

LXY_LOVE36的博客 122

C++软件异常分析概述

本文将详细讲述Windows系统中软件异常的分类以及常用的排查方法,给大家提供一个借鉴与参考。

dvlinker的技术专栏 4万+

AVL树详解及Java实现

AVL的平衡原理分析及实现

thehazardon的博客 1295

HyperLynx中层叠设计实例

这两种方式有点区别,前一种方式只是增加层,需要自行修改层的类型,后一种方式可以选定为某一种类型,如果是增加信号层,软件会默认同时增加一层介质层。层叠已经有8层,按照示例的层叠有4个信号层、3个地平面层和1个电源平面层,对照进行层名称(LayerName)、介质类型(Type)及用途(Usage)设置。在这列中,有的是白色,有的是淡蓝色。白色的说明可以修改,如第一行是介质,通常在最外层的介质有两个用途,阻焊层和介质,单击该行会出现一个下拉菜单,选择SolderMask,即为阻焊层。...

小幽余生不加糖 5879

AVL树----java版

/平衡因子//左孩子的引用//右子树的引用//父亲节点的引用我们需要把AVL定义为三叉树,同时增加bf记录每个节点的平衡因子,通过获取节点的平衡因子来调节树的平衡。三叉结构增加一个指针指向父亲节点,可以更好的在增加节点时修改父亲节点的平衡因子。

weixin_65846395的博客 1170

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

WINCC7.3破解文件

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

用Java实现AVL树

写出这篇文章,作者用了三天时间,文中有错误希望读者能指出,我会仔细勘误。欢迎大家讨论,同时也在讨论中学习知识。掌握AVL树的原理与代码编写,让海量数据也能够极速查询!

2401_89252636的博客 1160

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Java 实现 AVL树

AVL树的概念及其模拟实现

每篇博客都不是最终版,都会随着我的学习更新 1362

java实现AVL树

文章目录1.AVL概念2.图解分析2.1 模拟器地址2.2 普通树和AVL树2.3 最简单的旋转2.4单旋转2.5双旋转2.6实现3.代码3.1树节点3.2平衡代码3.3 完整代码4.测试5.参考书籍 1.AVL概念 AVL树是带有平衡条件的二叉查找树,也称为平衡二叉树。 最简单的实现方法就是保证树的左右子树具有相同的高度,保证树的深度是O(log N),但是这个条件过于严格难以使用需要放宽条件。...

谢文峰的博客 2728

AVL树的实现

因为5 < b子树的值 < 10,将b变成10的左子树,10变成5的右子树,5变成这棵树新的根,符合搜索树的规则,控制了平衡,同时这棵的高度恢复到了插⼊之前的h+2,符合旋转原则。,不断向上更新平衡因子,导致10的平衡因⼦从1变成2,10为根的树左右⾼度差超过1,违反平衡规则。1,当subLR原始平衡因子时-1时,左右双旋后parent,subL,subLR的平衡因子分别更新为1,0,0。2,当subLR原始平衡因子时1时,左右双旋后parent,subL,subLR的平衡因子分别更新为0,-1,0。

2301_76564849的博客 822

AVL树(Java语言)

平衡二叉树 平衡二叉树也叫平衡二叉查找树,又被称为AVL树,可以保证查询效率较高。它的特点是:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。 结点的平衡因子定义为:结点的左子树高度与右子树高度之差。显然,对一棵AVL树而言,其所有结点的平衡因子只能是-1,0,1.挡在一棵AVL树上插入一个结点时,有可能导致失衡,即出现绝对值大于1的平衡因子。 单旋转(左旋转) 插入70后失去平衡,调整过程如下:。 思路: 1、创建一个新的结点,值等于当前根节点的值。 2、把新

qq_49306008的博客 2749

AVL树的Java实现

  二叉搜索树有一个很大的弊端就是很不稳定。输入数字的顺序不同可能导致二叉树退化成链表;比如:顺序输入: 1 -> 5;与乱序输入:3,2,4,1,5;会有不同结果;  苏联的科学家G. M. Adelson-Velsky和E. M. Landis发明了自平衡的二叉搜索树:AVL(名字缩写)树;AVL树本质上还是一棵二叉搜索树,它的特点是:也就是说,AVL树,本质上是带了平衡功能的二叉查找树; htarget = max(hleft , hright) + 1;  例子:有2个子节点;比较左........

Myd 938

avl树 java_AVL树之 Java的实现

AVL树的介绍AVL树是高度平衡的而二叉树。它的特点是:AVL树中任何节点的两个子树的高度最大差别为1。上面的两张图片,左边的是AVL树,它的任何节点的两个子树的高度差别都<=1;而右边的不是AVL树,因为7的两颗子树的高度相差为2(以2为根节点的树的高度是3,而以8为根节点的树的高度是1)。AVL树的Java实现1. 节点1.1 节点定义public class AVLTree> {...

weixin_39865866的博客 296

AVL树Java语言实现

AVL树理解、证明

weixin_42111859的博客 756

avl树的java实现代码_AVL树的java实现

AVL树的定义自己百度去,这里给出自己用java的一个实现。package test;/*** @时间 2014-3-30* @version 0.1* @encode UTF-8* @功能* 1、AVL树的生成* 2、插入元素* 3、删除元素* 4、查找某一元素* @notice 树元素需实现Comparor接口* @see 《数据结构与算法分析》第4章4.4节* */public class ...

weixin_35780601的博客 362

AVL树Java实现

AVL树又叫平衡二插搜索树,二插搜索树的查找效率在极端情况下是比较低的,而AVL树会保证左右子树的高度差的绝对值不会超过1

爱敲代码的三毛的博客 646

使用AVL树实现Map

3、数组------》链表(数组转为链表是为了充分利用内存空间)------》BST(AVL(缺点是在插入节点时需要大量调整))------》RBT。一、数组在裂变扩容时可能会出现环、在数组元素转为链表之后选择尾插法插入节点、数组到链表到AVL到RBT的转换。1、节点:K和V,一对看,Pair(K,V)、height、left、right。解决方案:用删除节点的右子树的最小节点替换掉删除节点。2、情况二:删除节点的左节点为空右节点不为空。3、情况三:删除节点的左节点不为空右节点为空。

Watermelon_Mr的博客 977

java AVL树增删模拟

java模拟AVL树增删操作

qq_43479628的博客 926

java avl_AVL树(三)之 Java的实现

概要前面分别介绍了AVL树"C语言版本"和"C++版本",本章介绍AVL树的Java实现版本,它的算法与C语言和C++版本一样。内容包括:AVL树的介绍AVL树是高度平衡的而二叉树。它的特点是:AVL树中任何节点的两个子树的高度最大差别为1。上面的两张图片,左边的是AVL树,它的任何节点的两个子树的高度差别都<=1;而右边的不是AVL树,因为7的两颗子树的高度相差为2(以2为根节点的树的高度...

weixin_34536454的博客 254
上一篇: Java多线程四个案例
下一篇: 红黑树,位图的理解以及实现
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值