平衡二叉搜索树---java---黑马

news2024/11/29 6:26:40

平衡二叉搜索树

AVL树的实现

  • 二叉搜索树在插入和删除时,节点可能发生失衡;
  • 如果在插入和删除时通过旋转,始终让二叉搜索树保持平衡,称之为平衡二叉搜索树
  • AVL树是自平衡二叉搜索树的实现之一

LL

- 失衡节点(图中5红色)的`bf>1`,即左边更高
- 失衡节点的左孩子(图中3 黄色)的`bf>=0`,即左孩子这边也是左边更高或等高

在这里插入图片描述

LR

- 失衡节点(图中6)的`bf>1`,即左边更高
- 失衡节点的左孩子(图中2 黄色)的`bf<0`,即左孩子这边是右边更高

在这里插入图片描述

RL

-失衡节点(图中2)的`bf<-1`,即右边更高
-失衡节点的右孩子(图中6黄色)的`bf>0`,即右孩子这边是左边更高

在这里插入图片描述

RR

-失衡节点(图中2红色)的`bf<-1`,即右边更高
-失衡节点的右孩子(图中6黄色)的`bf<=0`,即右孩子这边是右边更高或者等高

在这里插入图片描述

public class AVLTree{
    
    static class AVLNode{
        int key;
        Object value;
        AVLNode left;
        AVLNode right;
        int height = 1;
        
        public AVLNode (int key, Object value) {
            this.key = key;
            this.value = value;
        }
        
        public AVLNode (int key) {
            this.key = key;
        }
        
        public AVLNode (int key, Object value, AVLNode left, AVLNode right) {
            this.key = key;
            this.value = value;
            this.left = left;
            this.right = right;
        }
    }
    
    // 求节点高度
    public int height(AVLNode node) {
        return node == 0 ? 0 : node.height;
    }
    
    // 更新节点高度(新增、删除、旋转)
    public void updateHeight(AVLNode node) {
        node.height = Math.max(height(node.left), height(node.right)) + 1;
    }
    
    // 平衡因子(balance factor) = 左子树高度-右子树高度
    // bf = 0, -1, 1, 表示左右平衡
    // bf > 1, 表示左子树高
    // bf < -1, 表示右子树高
    public int bf(TreeNode node) {
        return height(node.left) - height(node.right);
    }
    
    // 输入要旋转的节点,返回新节点----右旋
    private AVLNode rightRotate(AVLNode red) {
        AVLNode yellow = red.left;
        AVLNode green = yellow.right;
        yellow.right = red;
        red.left = green;
        updateHeight(red);
        updateHeight(yellow);
        return yellow;
    }
    
    // 输入要旋转的节点,返回新节点----左旋
    private AVLNode leftRotate(AVLNode red) {
        AVLNode yellow = red.right;
        AVLNode green = yellow.left;
        yellow.left = red;
        red.righ = green;
        updateHeight(red);
        updateHeight(yellow);
        return yellow;
    }
    
    // 先左旋,后右旋----先左旋左子树,后右旋根节点
    private AVLNode leftRightRotate(AVLNode node) {
        node.left = leftRotate(node.left);
        return rightRotate(node);
    }
    
    // 先右旋右子树,后左旋根节点
    private AVLNode rightLeftRotate(AVLNode node) {
        node.right = rightRotate(node.right);
        return leftRotate(node);
    }
    
    // 检查是否平衡
    private AVLNode balance(AVLNode node) {
        if (node == null) {
            return node;
        }
        int bf = bf(node);
        if (bf > 1 && bf(node.left) >= 0) {		//LL
            rightRotate(node);
        } else if (bf > 1 && bf(node.left) < 0) {	// LR
            leftRightRotate(node);
        } else if (bf < -1 && bf(node.right) > 0) {		// RL
            rightLeftRotate(node);
        } else if (bf < -1 && bf(node.right) <= 0) {	// RR	
            leftRotate(node);
        }
    }
    
    AVLNode root;
    
    public void put(int key, Object value) {
        return doPut(root, key, value);
    } 
    
    private ALVNode doPut(AVLNode node, int key, Object value) {
        // 1.找到空位,创建新节点
        if (node == null) {
            return new AVLNode(key, value);
        }
        // 2.树中存在节点,做更新操作
        if (node.key == key) {
            node.value = value;
            return node;
        }
        // 3.查找操作
        if (key < node.key) {
            node.left = doPut(node.left, key, value);
        }
        if (key > node.key) {
            node.right = doPut(node.right, key, value);
        }
        // 更新高度,检查是否平衡
        updateHeight(node);
        return balance(node);
    }
    
    public void remove(int key) {
        root = doRemove(root, key);
    }
    
    public AVLNode doRemove(AVLNode node, int key) {
        // 1.节点为空
        if (node == null) {
            return null;
        }
        // 2.寻找节点
        if (key < node.key) {
            node.left = doRemove(node.left, key);
        } else if (key > node.key) {
            node.right = doRemove(node.right, key);
        } else {
            // 3.找到节点,判断删除节点是否有孩子
            if (node.left == null && node.right == null) {
                return null;
            } else if(node.left == null) {
                node = node.right;
            } else if (node.right == null) {
                node = node.left;
            } else {		// 左右子树均在
                // 在待删除节点的右子树zhon寻找待删除节点的后继节点
               	AVLNode s = node.right;
                while (s.left != null) {
                    s = s.left;
                }
                // 找到后继节点
                s.right = doRemove(node.right, s.key);
                s.left = node.left;
                node = s;
            }
        }
        updateHeight(node);
        return balance(node);
    }
}

删除操作

Remove(node.right, s.key);
s.left = node.left;
node = s;
}
}
updateHeight(node);
return balance(node);
}
}


删除操作
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/c65de9476563476ebd30192166eb8b07.png#pic_center)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2189214.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

项目-坦克大战学习笔记-地图完善

之前我们详细讲解了怎么在地图上绘制墙&#xff0c;这次我们来完善整个地图&#xff0c; 地图的静态物体构成分为可破坏的墙体&#xff0c;不可破坏的铁块&#xff0c;以及最终boos 那我们为了方便存储将三个对象分开放为3个列表 private static List<gudin> walllist…

vscode有问题

开始给我报错&#xff0c;说命名不规范 然后我就改&#xff0c;改了好几遍之后还是报错。问了ai&#xff0c;也用它的方法改了&#xff0c;还是报错。。。 然后关掉vscode&#xff0c;重启&#xff0c;&#xff0c;&#xff0c;&#xff0c;&#xff0c;&#xff0c;运行成功

【算法系列-链表】删除链表的倒数第N个结点

【算法系列-链表】删除链表的倒数第N个结点 文章目录 【算法系列-链表】删除链表的倒数第N个结点1. 算法分析&#x1f6f8;2. 模拟解决问题2.1 思路分析&#x1f3af;2.2 代码示例&#x1f330; 3. 双指针(快慢指针)解决问题3.1 思路分析&#x1f3af;3.2 代码示例&#x1f330…

Web-Machine-N7解题过程

1.主机探测 arp-scan -lnmap -sn 192.168.1.0/24sudo netdiscover -r 192.168.1.0/24masscan -p0-65535 192.168.1.0/24 2.端口扫描 nmap -A -sC -sT -sV 192.168.1.188 --min-rate 10000 &#xff08;简略扫描&#xff09;nmap -sS 192.168.1.188 -A&#xff1a; 启用操作系…

vue的图片显示

通过参数 调用方法 进行显示图片 方法一: 方法二:

使用TM1618控制LED了解P-MOS和N-MOS的开漏输出的不同

数据手册上的截取内容 推荐的共阴/阳极电路 可以发现GRID总接LED的负极&#xff0c;SEG引脚接的是LED 正极 分析输出的MOS管类型可以很好的知道原因 图片来源 通过都是开漏输出可以看出&#xff0c;引脚引出的内部电路是不同的。P-mos引出的是漏极&#xff0c;导通时&#…

平面电磁波的能量传输速度——就记平均坡印廷矢量/平均能量密度(物理意义,坡印廷是单位时间该点流过的能量,能量密度表示该店有多少能量。如果能量密度不变,经过流动速度是2/s,则1s流过的能量就是2*密度

能量传输速度 平均坡印廷矢量的模&#xff08;功率流密度&#xff09;/ 电磁波平均能量密度&#xff08;电场和磁场的都算进去&#xff09; 能量传输速度等于相速度 但是文心给出的能量流动速度的定义是

2. 术语解释(类、成员变量、行为、属性、this)以及注销账号和空指针异常

文章目录 1. 类2. 成员变量3. 行为4. 属性5. zhangDog.name 以及 zhangDog.sleep()解析6. this① 提出问题② 解决方案③ 进一步完善&#xff1a;引入this 7. 注销账号8. 空指针异常9. 内容出处 1. 类 我们的目的是不是要给狗写一个程序&#xff0c;而且要让所有狗都能用&#…

20241004给荣品RD-RK3588-AHD开发板刷Rockchip原厂的Android12【HDMI0显示】

20241004给荣品RD-RK3588-AHD开发板刷Rockchip原厂的Android12【HDMI0显示】 2024/10/4 19:40 1、配置RK3588S的默认DTS为&#xff1a;rk3588s-evb4-lp4x-v10.dts D:\Android\rk3588s4_3588a12\device\rockchip\rk3588\rk3588s_s\BoardConfig.mk Z:\rk3588s4_3588a12\device\ro…

【论文笔记】Efficient LoFTR: Semi-Dense Local Feature Matching with Sparse-Like Speed

【引用格式】&#xff1a;Wang Y, He X, Peng S, et al. Efficient LoFTR: Semi-dense local feature matching with sparse-like speed[C]//Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2024: 21666-21675. 【网址】&#xff1a;ht…

PostgreSQL Docker Error – 5432: 地址已被占用

PostgreSQL Docker Error – 5432: 地址已被占用 今天在学习【Spring Boot React】价值79.9美元&#xff0c;全栈开发&#xff0c;搭建个人网站、做毕业设计、试试这套课程第17~21节视频的时候&#xff0c;发现运行docker run --name demo-postgres -e POSTGRES_PASSWORDpass…

数据集-目标检测系列- 货船 检测数据集 freighter>> DataBall

数据集-目标检测系列- 货船 检测数据集 freighter>> DataBall 数据集-目标检测系列- 货船 检测数据集 freighter>> DataBall 数据量&#xff1a;3k 想要进一步了解&#xff0c;请联系。 DataBall 助力快速掌握数据集的信息和使用方式&#xff0c;会员享有 百种…

高效参数微调

一、增加额外参数的方法 这些方法通过向模型中添加额外的可训练参数&#xff0c;而不修改原有的预训练模型参数。 1. Prefix Tuning&#xff08;前缀微调&#xff09; 原理&#xff1a;在每一层的输入添加一组可训练的“前缀”向量&#xff0c;这些前缀向量会影响模型的输出…

使用PL/SQL Deverloper过程遇见的问题

目录 背景: ORA-01031权限问题&#xff1a; PL/SQL Deverloper显示Oravle中存在的所有表&#xff1a; PL/SQL Deverloper优点: 背景: PL/SQL Developer是由Allround Automations公司开发的一款集成开发环境(IDE),它专门面向Oracle数据库存储的程序单元的开发。随着越来越多…

Python+Matplotlib可视化初等函数示例

import numpy as np import matplotlib.pyplot as pltplt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] Falsefig, axs plt.subplots(2, 3, figsize(15, 10))# 1. 幂函数 x np.linspace(-2, 2, 200) axs[0, 0].plot(x, x**2, labely x^2) axs[0,…

每日OJ题_牛客_OR63删除公共字符_哈希_C++_Java

目录 牛客_OR63删除公共字符_哈希 题目解析 C代码1 C代码2 Java代码 牛客_OR63删除公共字符_哈希 删除公共字符_牛客题霸_牛客网 (nowcoder.com) 题目解析 用哈希表记录一下字符串的字符信息即可。 C代码1 #include <iostream> #include <string> #includ…

C语言 动态数据结构的C语言实现内存映像

C程序的内存映像 C程序中变量的内存分配方式  C程序中变量的内存分配方式  从静态存储区分配  全局变量和静态变量 C程序中变量的内存分配方式  从静态存储区分配  全局变量和静态变量  在栈上分配  存放函数参数值&#xff0c;局部变量值等  …

角膜移植难题现,传统方式缺陷显,创新水凝胶破局

大家好&#xff01;今天来了解一篇天然聚合物衍生光固化生物粘附水凝胶研究——《Natural polymer-derived photocurable bioadhesive hydrogels for sutureless keratoplasty》发表于《Bioactive Materials》。本文介绍了一种用于无缝合角膜移植术的天然聚合物衍生光固化生物粘…

Leetcode—76. 最小覆盖子串【困难】

2024每日刷题&#xff08;167&#xff09; Leetcode—76. 最小覆盖子串 C实现代码 class Solution { public:string minWindow(string s, string t) {int bestL -1;int l 0, r 0;vector<int> cnt(128);for(const char c: t) {cnt[c];}int require t.length();int m…

程序员必备!面向Prompt编程全攻略

前言 程序员工作的终极意义&#xff0c;就是干掉复杂度&#xff0c;用一套通用的方法解决大部分问题。在大模型时代&#xff0c;这个通用的方法就是——Prompt 工程。作为用好大模型最重要的武器&#xff0c;Prompt 的好坏对模型效果有着决定性的影响。 然而&#xff0c;网络…