数据结构入门-10-AVL

news2025/1/11 20:40:59

文章目录

  • 一、AVL的性质
    • 1.2 平衡二叉树定义
  • 二、添加需达到平衡
    • 2.1 平衡因子
      • 2.1.2 平衡因子的实现
    • 2.2 判断该二叉树是否为平衡二叉树
    • 2.3 左旋右旋
      • 2.3.1 左旋LL右旋RR基本原理
      • 2.3.2 LR RL
        • LR
        • RL
  • 三、AVL中删除

一、AVL的性质

平衡二叉树
AVL树得名于它的俄罗斯发明者G. M. Adelson-Velsky和E. M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它
在这里插入图片描述
防止二分搜索树出现退化成链表的情况

1.2 平衡二叉树定义

之前讲过的 完全二叉树:差值不会超过1,缺失一定在右下侧
在这里插入图片描述
平衡二叉树:高度(左子树) - (右子树) <= 1

和完全二叉树的区别:
在这里插入图片描述

二、添加需达到平衡

2.1 平衡因子

再次2添加带来的问题:
在这里插入图片描述

  1. 标记节点的高度
  2. 计算平衡因子
    在这里插入图片描述
  3. 平衡因子 > 1 就需要重新整理

2.1.2 平衡因子的实现

import java.util.ArrayList;

public class AVLTree<K extends Comparable<K>, V> {

    private class Node{
        public K key;
        public V value;
        public Node left, right;
        public int height;

        public Node(K key, V value){
            this.key = key;
            this.value = value;
            left = null;
            right = null;
            height = 1;
        }
    }

    private Node root;
    private int size;

    public AVLTree(){
        root = null;
        size = 0;
    }

    public int getSize(){
        return size;
    }

    public boolean isEmpty(){
        return size == 0;
    }

    // 获得节点node的高度
    private int getHeight(Node node){
        if(node == null)
            return 0;
        return node.height;
    }

    // 获得节点node的平衡因子
    private int getBalanceFactor(Node node){
        if(node == null)
            return 0;
        return getHeight(node.left) - getHeight(node.right);
    }

    // 向二分搜索树中添加新的元素(key, value)
    public void add(K key, V value){
        root = add(root, key, value);
    }

    // 向以node为根的二分搜索树中插入元素(key, value),递归算法
    // 返回插入新节点后二分搜索树的根
    private Node add(Node node, K key, V value){

        if(node == null){
            size ++;
            return new Node(key, value);
        }

        if(key.compareTo(node.key) < 0)
            node.left = add(node.left, key, value);
        else if(key.compareTo(node.key) > 0)
            node.right = add(node.right, key, value);
        else // key.compareTo(node.key) == 0
            node.value = value;

        // 更新height
        node.height = 1 + Math.max(getHeight(node.left), getHeight(node.right));

        // 计算平衡因子
        int balanceFactor = getBalanceFactor(node);
        if(Math.abs(balanceFactor) > 1)
            System.out.println("unbalanced : " + balanceFactor);

        return node;
    }

2.2 判断该二叉树是否为平衡二叉树

// 判断该二叉树是否是一棵二分搜索树
    public boolean isBST(){

        ArrayList<K> keys = new ArrayList<>();
        inOrder(root, keys);
        for(int i = 1 ; i < keys.size() ; i ++)
            if(keys.get(i - 1).compareTo(keys.get(i)) > 0)
                return false;
        return true;
    }

//用中序遍历,查看是否是从小到大
    private void inOrder(Node node, ArrayList<K> keys){

        if(node == null)
            return;

        inOrder(node.left, keys);
        keys.add(node.key);
        inOrder(node.right, keys);
    }

判断树是否为平衡二叉树


    // 判断该二叉树是否是一棵平衡二叉树
    public boolean isBalanced(){
        return isBalanced(root);
    }

    // 判断以Node为根的二叉树是否是一棵平衡二叉树,递归算法
    private boolean isBalanced(Node node){

        if(node == null)
            return true;

        int balanceFactor = getBalanceFactor(node);
        if(Math.abs(balanceFactor) > 1)
            return false;
        return isBalanced(node.left) && isBalanced(node.right);
    }

    // 获得节点node的高度
    private int getHeight(Node node){
        if(node == null)
            return 0;
        return node.height;
    }

    // 获得节点node的平衡因子
    private int getBalanceFactor(Node node){
        if(node == null)
            return 0;
        return getHeight(node.left) - getHeight(node.right);
    }

2.3 左旋右旋

2.3.1 左旋LL右旋RR基本原理

这个左旋可不能减肥

之前在BST中的add后维护
在这里插入图片描述

在AVL中,之前的例子 add(2)
在这里插入图片描述
8的平衡因子2
简化刚才的例子,T1…5 为叶子 可能为空
在这里插入图片描述
在这里插入图片描述

    // 对节点y进行向右旋转操作,返回旋转后新的根节点x
    //        y                              x
    //       / \                           /   \
    //      x   T4     向右旋转 (y)        z     y
    //     / \       - - - - - - - ->    / \   / \
    //    z   T3                       T1  T2 T3 T4
    //   / \
    // T1   T2
    private Node rightRotate(Node y) {
        Node x = y.left;
        Node T3 = x.right;

        // 向右旋转过程
        x.right = y;
        y.left = T3;

        // 更新height
        y.height = Math.max(getHeight(y.left), getHeight(y.right)) + 1;
        x.height = Math.max(getHeight(x.left), getHeight(x.right)) + 1;

        return x;
    }

左旋转类似


    // 对节点y进行向左旋转操作,返回旋转后新的根节点x
    //    y                             x
    //  /  \                          /   \
    // T1   x      向左旋转 (y)       y     z
    //     / \   - - - - - - - ->   / \   / \
    //   T2  z                     T1 T2 T3 T4
    //      / \
    //     T3 T4
    private Node leftRotate(Node y) {
        Node x = y.right;
        Node T2 = x.left;

        // 向左旋转过程
        x.left = y;
        y.right = T2;

        // 更新height
        y.height = Math.max(getHeight(y.left), getHeight(y.right)) + 1;
        x.height = Math.max(getHeight(x.left), getHeight(x.right)) + 1;

        return x;
    }

2.3.2 LR RL

当插入4 10 的时候,就不能简单的旋转了
在这里插入图片描述
因为10 > 8 所以直接旋转还是不满足BST

在这里插入图片描述
例子中的是LR的情况,需要先对x做一次左旋转

LR

在这里插入图片描述
转换成了LL的情况
在这里插入图片描述

RL

在这里插入图片描述
转换成了RR
在这里插入图片描述

    // 向以node为根的二分搜索树中插入元素(key, value),递归算法
    // 返回插入新节点后二分搜索树的根
    private Node add(Node node, K key, V value){

        if(node == null){
            size ++;
            return new Node(key, value);
        }

        if(key.compareTo(node.key) < 0)
            node.left = add(node.left, key, value);
        else if(key.compareTo(node.key) > 0)
            node.right = add(node.right, key, value);
        else // key.compareTo(node.key) == 0
            node.value = value;

        // 更新height
        node.height = 1 + Math.max(getHeight(node.left), getHeight(node.right));

        // 计算平衡因子
        int balanceFactor = getBalanceFactor(node);

        // 平衡维护
        if (balanceFactor > 1 && getBalanceFactor(node.left) >= 0)
            return rightRotate(node);

        if (balanceFactor < -1 && getBalanceFactor(node.right) <= 0)
            return leftRotate(node);
        //LR
        if (balanceFactor > 1 && getBalanceFactor(node.left) < 0) {
            node.left = leftRotate(node.left);
            return rightRotate(node);
        }
        //RL
        if (balanceFactor < -1 && getBalanceFactor(node.right) > 0) {
            node.right = rightRotate(node.right);
            return leftRotate(node);
        }

        return node;
    }

三、AVL中删除

和添加类似

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

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

相关文章

信息系统项目管理师第四版知识摘编:第23章 组织通用管理​

第23章 组织通用管理​ 组织通用管理是项目管理的关键前提和基础&#xff0c;它为项目管理提供思想路线和基本原则与方法&#xff0c;项目管理则是通用管理方法在特定场景下的具体表现。​ 23.1人力资源管理​ 23.1.1人力资源管理基础​ 在人力资源管理方面&#xff0c;组织…

对XSS攻击进行的一些总结

简介 XSS漏洞最早被发现是在1996年&#xff0c;由于JavaScript的出现&#xff0c;导致在Web应用程序中存在了一些安全问题。在1997年&#xff0c;高智文(Gareth Owen)也就是“XSS之父”&#xff0c;在他的博客中描述了一种称为“脚本注入”(script injection)的攻击技术&#x…

分享一个RecyclerView嵌套webview 滑动不流畅的解决方法

因RecyclerView 和webview 或者X5的webview 都具有滑动的功能 所以在做嵌套的时候 会出现滑动不流畅 等问题 解决思路 就是判断滑动的时候 是否自身消耗 或者父布局的RecycleView消耗 开发中还遇到个问题 就是 更换成x5的时候 getScrolly() 返回的一直是0 改成getWebScrollY(…

2022国赛16:神州路由器交换机BGP配置实例1

实验拓扑图 一、基本配置: R1配置: Router>ena Router#conf Router_config#host R1 R1_config#int g0/0 R1_config_g0/0#ip add 202.11.1.1 255.255.255.252 R1_config_g0/0#int l0 R1_config_l0#ip add 1.1.1.1 255.255.255.255 R1_confi

【iOS】iOS语音通话回音消除(AEC)技术实现

一、前言 在语音通话、互动直播、语音转文字类应用或者游戏中&#xff0c;需要采集用户的麦克风音频数据&#xff0c;然后将音频数据发送给其它终端或者语音识别服务。如果直接使用采集的麦克风数据&#xff0c;就会存在回音问题。所谓回音就是在语音通话过程中&#xff0c;如…

Minikube安装、运行

1.Minikube是什么 本地的k8s集群&#xff0c;方便开发者学习k8s。 2.安装的前提条件 2个CPU货以上。2G内存或以上。20G磁盘或以上。可以链接互联网。安装docker&#xff08;官网说或者一个虚拟环境&#xff0c;这个不考虑&#xff09;。 3.官网地址 minikube start | minik…

docker部署mysql5.7

1、拉取镜像 docker pull mysql:5.72、运行容器 docker run -p 3306:3306 --name my-mysql -v $PWD/conf:/etc/mysql -v $PWD/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORDqazWSX123 -d mysql:5.7-v $PWD/conf:/etc/mysql指令是挂载mysql的配置文件到宿主机 -v $PWD/data:/var…

基于Java+SpringBoot+vue的口腔管家平台设计与实现【源码(完整源码请私聊)+论文+演示视频+包运行成功】

博主介绍&#xff1a;专注于Java技术领域和毕业项目实战 &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb; 不然下次找不到哟 Java项目精品实战案例&#xff08;300套&#xff09; 目录 一、效果演示 二、…

DJ3-4 实时调度

目录 3.4.1 实现实时调度的基本条件 1. 提供必要的信息 2. 系统的处理能力强 3. 采用抢占式调度机制 4. 具有快速切换机制 3.4.2 实时调度算法的分类 1. 非抢占式调度算法 2. 抢占式调度算法 3.4.3 常用的几种实时调度算法 1. 最早截止时间优先 EDF&#xff08;Ea…

拼多多按关键字搜索商品 API

一、拼多多平台优势&#xff1a; 1、独创拼团模式 拼团拼单是拼多多独创的营销模式&#xff0c;其特点是基于人脉社交的裂变传播&#xff0c;非常具有传播性。 由于本身走低价路线&#xff0c;加上拼单折扣&#xff0c;商品的分享和人群裂变效果非常明显&#xff0c;电商前期…

单向链表和双向链表的实现 (LinkedList)

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点!人生格言&#xff1a;当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友一起加油喔&#x1f9be;&am…

Markdown发布静态网页

解析markdown_利用 markdown 生成页面实践_灰色派的博客-CSDN博客 业务需求 1.为什么要用 markdown 来生成页面&#xff1f; 对于展示型网站&#xff0c;例如官网这种场景&#xff0c;会有很多小的页面&#xff0c;运营会根据市场时刻有增删修改类似页面的需求&#xff0c;如…

MapReduce笔记

总计&#xff1a;切片就是对一个文件按逻辑进行切片&#xff0c;默认每128m为一个切片&#xff0c;不是物理切片&#xff0c;每个切片对应着一个mapTask进行处理。而且切片是针对每一个文件进行切片的&#xff0c;即一个文件一个文件切片&#xff0c;不是把所以待处理的文件总量…

游戏运营是什么?运营专员需要具备什么能力?

游戏运营主要是负责公司游戏的运营计划制定&#xff0c;包含通过用户对游戏的反馈和数据分析找出产品所存在的问题&#xff0c;并进行优化。通过各种促销活动、节假日实行游戏付费内容来刺激消费&#xff0c;实现游戏和品牌双赢的打造过程。 游戏运营分很多种&#xff1a;用户…

python获取数据类型

之前将字面量时就将到过 数据是有类型的 python的数据类型还挺多的 而现阶段 我们主要接触了 字符串 浮点数 正整数 对应的类型 都有自己的名称 字符串 string 浮点数 float 正整数 int python提供了一个type语句 用于验证数据类型 我们打开编辑工具 编写代码如下 print(typ…

每日一问-ChapGPT-20230416-中医基础-经络

文章目录每日一问-ChapGPT系列起因每日一问-ChapGPT-20230416-中医基础-经络人体的经络有哪些&#xff0c;有什么规律&#xff0c;怎么记忆问诊的具体细节当日总结每日一问-ChapGPT系列起因 近来看了新闻&#xff0c;看了各种媒体&#xff0c;抖音&#xff0c;官媒&#xff0c…

FPGA与ASIC的区别

先来看张图&#xff0c;本图体现出了集成电路产业链&#xff1a;设计业、制造业、封测业。 关于制造、封装测试我们看两张图稍作了解即可&#xff1a; 数字IC ASIC设计流程及EDA工具&#xff1a; &#xff08;1&#xff09;了解数字IC设计&#xff1a;在VLSI时代&#xff…

MySQL数据库之表的增删改查(基础)

目录1 新增&#xff08;Create&#xff09;1.1 单行数据 全列插入1.2 多行数据 全列插入2 查询&#xff08;Retrieve&#xff09;2.1 全列查询2.2 指定列查询2.3 查询字段为表达式2.4 别名2.5 去重: DISTINCT2.6 排序: ORDER BY2.7 条件查询: WHERE2.8 分页查询: LIMIT3 修改…

基于html+css的图片展示10

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

10个有趣python模块

一、说明 Python 是一种高级、解释型和通用动态编程语言&#xff0c;侧重于代码的可读性。它在许多组织中使用&#xff0c;因为它支持多种编程范例。它还执行自动内存管理。它是世界上最受欢迎的编程语言之一。这是有很多原因的&#xff1a; 这很容易学习。 它超级多才多艺。 …