使用AVL树实现Map

一、数组在裂变扩容时可能会出现环、在数组元素转为链表之后选择尾插法插入节点、数组到链表到AVL到RBT的转换

1、数组在裂变扩容时链表中的节点计算出来的位置可能也会发生变化,在多线程情况下调整节点位置可能会出现环。

2、数组中的数组元素转为链表后插入新节点时应选择采用尾插法,因为头插法在并发时可能会产生(jdk1.7之前出现过这种问题)

3、数组------》链表(数组转为链表是为了充分利用内存空间)------》BST(AVL(缺点是在插入节点时需要大量调整))------》RBT

二、HashMap要实现的方法

1、put(K,V):添加键值对

2、get(K):根据键找对应的键值对

3、remove(K):根据键移除对应的键值对

三、实现一棵树的底层有两种方式

1、数组法

浪费一些空间,找起来比较容易

2、节点法

节省空间、访问没有数组快

五、实现AVL树(节点、AVL)

1、节点:K和V,一对看,Pair(K,V)、height、left、right

2、AVLNode<K,V>:K、V是泛型,泛型就是不确定是什么类型

六、Car c = new Car();这行代码在多线程环境下运行是否会出现问题

(1)线程的三大特性

原子性、可见性、有序性

(2) new Car()时发生了三件事

开辟内存空间、初始化对象、引用指向对象

(3)Car c = new Car();这行代码在多线程环境下运行可能会出现对象未初始化异常

(4)解决方案:sychronized(同步锁)、Asychronized(异步锁)

(5)数据库中违背线程无序性的案例

在使用MyBatis框架时,使用SQL语句对数据库进行查询时查询出来的结果是使用Entity对其进行封装的,如果未创建代理对象,就直接对Entity进行访问,会违背线程无序性,出现错误

七、向AVL树中添加节点之后调整平衡的四种情况

1、情况一:LL型

解决方案:右旋

/*** 将当前节点右旋并返回新的节点* @param node 当前节点* @return 新节点*/private AVLNode<K,V> rightRotate(AVLNode<K,V> node){AVLNode<K,V> X = node.left;AVLNode<K,V> T2 = X.right;node.left = T2;X.right = node;// 更新X节点与node节点的高度X.height = Math.max(getHeight(X.left), getHeight(X.right)) + 1;node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;return X;}

2、情况二:RR型

解决方案:左旋

/*** 将当前节点左旋并返回新的节点* @param node 当前节点* @return 新节点*/private AVLNode<K,V> leftRotate(AVLNode<K,V> node){AVLNode<K,V> X = node.right;AVLNode<K,V> T2 = X.left;node.right = T2;X.left = node;// 更新X节点与node节点的高度X.height = Math.max(getHeight(X.left), getHeight(X.right)) + 1;node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;return X;}

3、情况三:LR型

解决方案:先左旋后右旋

// LR 先左旋后右旋if(bf > 1 && balanceFactor(node.left) <= 0){node.left = leftRotate(node.left);return rightRotate(node);}

4、情况四:RL型

解决方案:先右旋后左旋

if(bf < -1 && balanceFactor(node.right) >= 0){node.right = rightRotate(node.right);return leftRotate(node);}

八、从AVL树中删除节点的四种情况

1、情况一:删除节点的左子树和右子树都不为空

解决方案:用删除节点的右子树的最小节点替换掉删除节点

if(node.left != null && node.right != null){AVLNode<K,V> midNode = midNode(node.right);midNode.right = remove(node.right,midNode.pair.key);size ++;midNode.left = node.left;resultNode = midNode;}

2、情况二:删除节点的左节点为空右节点不为空

解决方案:将删除节点的右节点作为新节点

if(node.left == null && node.right != null){resultNode = node.right;}

3、情况三:删除节点的左节点不为空右节点为空

解决方案:将删除节点的左节点作为新节点

if(node.right == null && node.left != null){resultNode = node.left;}

4、情况四:删除节点的左右节点都不为空

解决方案:将null作为新节点

if(node.left == null && node.right == null){resultNode = null;
}

九、检查电脑上有多少行java源代码

public class StatisticsCodeCount {public static int count;public static void Statistics(File file) throws IOException {// 文件if(file.isFile()){if(file.getName().endsWith(".java")){BufferedReader reader = new BufferedReader(new FileReader(file));String line = null;while((line = reader.readLine()) != null){count++;}reader.close();}return;}// 文件夹File[] files = file.listFiles();if(files != null){for(File file1: files){Statistics(file1);}}}public static void main(String[] args) throws IOException {String path = "D:/";File file = new File(path);Statistics(file);System.out.println(StatisticsCodeCount.count*0.8);}
}

十、使用AVL树实现Map

package com.ffyc.avl;/*** 绑定key-value的对象* @param <K> key* @param <V> value*/
public class Pair<K extends Comparable<K>,V> {public K key;public V val;public Pair() {}public Pair(K key, V val) {this.key = key;this.val = val;}@Overridepublic String toString() {return "Pair{" +"key=" + key +", val=" + val +'}';}
}
package com.ffyc.avl;public class AVLNode <K extends Comparable<K>,V> {public int height;// 与节点不相关的,节点高度public Pair<K,V> pair;// 节点值public AVLNode<K,V> left;public AVLNode<K,V> right;public AVLNode() {}public AVLNode(Pair<K, V> pair) {this.pair = pair;this.height = 1;}public static void main(String[] args) {System.out.println(Math.cbrt(1000));}
}
package com.ffyc.avl;/*** AVL树* @param <K> key* @param <V> value*/
public class AVLTree <K extends Comparable<K>,V> {private int size;// 树中节点数目/*** 获取树中的节点数目* @return*/public int getSize(){return size;}/*** 获取当前节点的高度* @param node 当前节点* @return 高度*/private int getHeight(AVLNode<K,V> node){if(node == null) return 0;return node.height;}/*** 获取当前节点的平衡因子* @param node 当前节点* @return 平衡因子* bf > 1 不平衡 左子 >> 右子* bf < -1 不平衡 右子 << 左子* bf == 0 平衡* bf == 1 当前平衡* bf == -1 当前平衡*/private int balanceFactor(AVLNode<K,V> node){if(node == null) return 0;// 特殊处理return getHeight(node.left) - getHeight(node.right);}/*** 将当前节点右旋并返回新的节点* @param node 当前节点* @return 新节点*/private AVLNode<K,V> rightRotate(AVLNode<K,V> node){AVLNode<K,V> X = node.left;AVLNode<K,V> T2 = X.right;node.left = T2;X.right = node;// 更新X节点与node节点的高度X.height = Math.max(getHeight(X.left), getHeight(X.right)) + 1;node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;return X;}/*** 将当前节点左旋并返回新的节点* @param node 当前节点* @return 新节点*/private AVLNode<K,V> leftRotate(AVLNode<K,V> node){AVLNode<K,V> X = node.right;AVLNode<K,V> T2 = X.left;node.right = T2;X.left = node;// 更新X节点与node节点的高度X.height = Math.max(getHeight(X.left), getHeight(X.right)) + 1;node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;return X;}/*** 在当前节点中插入值为pair的节点* @param node 当前节点* @param pair 节点值 key-value绑定对象* @return 插入新节点后的根节点*/public AVLNode<K,V> insert(AVLNode<K,V> node,Pair<K,V> pair){if(node == null){size++;return new AVLNode<>(pair);}// key相等,做数据更新if(pair.key.compareTo(node.pair.key) == 0){node.pair.val = pair.val;}else if(pair.key.compareTo(node.pair.key) < 0){node.left = insert(node.left, pair);}else{node.right = insert(node.right, pair);}// 更新node的高度node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;// 计算node的平衡因子int bf = balanceFactor(node);// LL 右旋if(bf > 1 && balanceFactor(node.left) >= 0){return  rightRotate(node);}// RR 左旋if(bf < -1 && balanceFactor(node.right) <= 0){return leftRotate(node);}// LR 先左旋后右旋if(bf > 1 && balanceFactor(node.left) <= 0){node.left = leftRotate(node.left);return rightRotate(node);}// RL 先右旋后左旋if(bf < -1 && balanceFactor(node.right) >= 0){node.right = rightRotate(node.right);return leftRotate(node);}return node;}/*** 从当前节点中查询键为key的节点* @param node 当前节点* @param key 键* @return 键为key的节点*/public AVLNode<K,V> find(AVLNode<K,V> node, K key){if(node == null) return null;if(key.compareTo(node.pair.key) == 0){return  node;}else if(key.compareTo(node.pair.key) < 0){return find(node.left, key);}else{return find(node.right, key);}}/*** 获取当前节点的最小节点* @param node 当前节点* @return 最小节点*/private AVLNode<K,V> midNode(AVLNode<K,V> node){if(node == null) return null;while (node.left != null){node = node.left;}return node;}/*** 从当前节点中删除键为key的节点* @param node 当前节点* @param key* @return 新节点*/public AVLNode<K,V> remove(AVLNode<K,V> node, K key){if(node == null) return null;AVLNode<K,V> resultNode = null;if(key.compareTo(node.pair.key) == 0){// key找到了if(node.left == null){resultNode = node.right;}if(node.right == null){resultNode = node.left;}if(node.left != null && node.right != null){AVLNode<K,V> midNode = midNode(node.right);midNode.right = remove(node.right,midNode.pair.key);size ++;midNode.left = node.left;resultNode = midNode;}size --;}if(key.compareTo(node.pair.key) < 0){node.left = remove(node.left, key);resultNode = node;}if(key.compareTo(node.pair.key) > 0){node.right = remove(node.right, key);resultNode = node;}// 更新高度,调整平衡// 更新resultNode的高度if(resultNode != null){resultNode.height = Math.max(getHeight(resultNode.left), getHeight(resultNode.right)) + 1;// 计算node的平衡因子int bf = balanceFactor(resultNode);// LL 右旋if(bf > 1 && balanceFactor(resultNode.left) >= 0){return  rightRotate(resultNode);}// RR 左旋if(bf < -1 && balanceFactor(resultNode.right) <= 0){return leftRotate(resultNode);}// LR 先左旋后右旋if(bf > 1 && balanceFactor(resultNode.left) <= 0){resultNode.left = leftRotate(resultNode.left);return rightRotate(resultNode);}// RL 先右旋后左旋if(bf < -1 && balanceFactor(resultNode.right) >= 0){resultNode.right = rightRotate(resultNode.right);return leftRotate(resultNode);}}return resultNode;}
}
package com.ffyc.avl;public class TestAVL {public static void main(String[] args) {AVLTree<Integer,Integer> tree = new AVLTree<>();AVLNode<Integer,Integer> root = null;root = tree.insert(root, new Pair<>(1,15));root = tree.insert(root, new Pair<>(4,22));root = tree.insert(root, new Pair<>(2,11));root = tree.insert(root, new Pair<>(6,25));root = tree.insert(root, new Pair<>(6,99));System.out.println("树中节点的数量:"+tree.getSize());root = tree.remove(root, 9);System.out.println("树中节点的数量:"+tree.getSize());System.out.println(tree.find(root, 4));}
}

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

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

相关文章

设计模式 享元模式(Flyweight Pattern)

享元模式 简绍 享元模式&#xff08;Flyweight Pattern&#xff09;是一种结构型设计模式&#xff0c;它的目的是通过共享技术来有效地支持大量细粒度的对象。享元模式可以极大地减少内存的使用&#xff0c;从而提高程序的性能。它特别适用于需要创建大量相似对象的场景&#…

Cypress安装与启动(开始学习记录)

一 Cypress安装 使用npm安装 1.查看node.js npm的版本&#xff0c;输入 npm --version 和 node --version&#xff0c;node.js没安装的可以去中文网下载最新稳定版安装&#xff0c;npm不建议升级到最新版本&#xff0c;会导致安装Cypress时Error: Cannot find module ansi-st…

在已安装的openresty上添加安装upstream模块报错的解决以及使用Consul服务发现时定时变更nginx的upstream的shell脚本

一、在已经安装好的openresty环境上添加安装upstream模块报错&#xff1a; 在已经安装好的openresty环境上添加安装upstream模块报错&#xff1a;http upstream check module can not find any check server, make sure you ve added the check 的问题解决。 服务器上已经安装好…

idea中java及java web项目的常见问题

1、乱码问题&#xff0c;主要有几处地方&#xff0c;需要检查。 ①确保文件编码&#xff0c;其实主要就是在idea启动文件中&#xff0c;增加了 -Dfile.encodingUTF-8的设置 ②编辑器默认编码&#xff0c;都改为UTF-8 ③Tomcat的运行配置&#xff0c;编码也改为UTF-8,同样使用…

SpringBoot3核心特性-核心原理

目录 传送门前言一、事件和监听器1、生命周期监听2、事件触发时机 二、自动配置原理1、入门理解1.1、自动配置流程1.2、SPI机制1.3、功能开关 2、进阶理解2.1、 SpringBootApplication2.2、 完整启动加载流程 三、自定义starter1、业务代码2、基本抽取3、使用EnableXxx机制4、完…

zynq的PS端mac与RTL8211F的连接要点

目录 1 VCCO_MIO12 PS_MIO_VREF3 PS的引脚4 RXDLY TXDLY5 ZYNQ的MAC可以调整延时吗 1 VCCO_MIO1 接1.8V 2 PS_MIO_VREF 接0.9V&#xff0c;可通过电阻分压 可通过电阻分压 3 PS的引脚 4 RXDLY TXDLY RXDLY RXD[0] TXDLY RXD[1] 与XC7Z020的PS端MAC连接&#xff0c;必须…

CVE-2024-2389 未经身份验证的命令注入

什么是 Progress Flowmon? Progress Flowmon 是一种网络监控和分析工具,可提供对网络流量、性能和安全性的全面洞察。Flowmon 将 Nette PHP 框架用于其 Web 应用程序。 未经身份验证的路由 我们开始在“AllowedModulesDecider.php”文件中枚举未经身份验证的端点,这是一个描…

1.pytest基础知识(默认的测试用例的规则以及基础应用)

一、pytest单元测试框架 1&#xff09;什么是单元测试框架 单元测试是指再软件开发当中&#xff0c;针对软件的最小单位&#xff08;函数&#xff0c;方法&#xff09;进行正确性的检查测试。 2&#xff09;单元测试框架 java&#xff1a;junit和testing python&#xff1a;un…

arcgisPro地理配准

1、添加图像 2、在【影像】选项卡中&#xff0c;点击【地理配准】 3、 点击添加控制点 4、选择影像左上角格点&#xff0c;然后右击填入目标点的投影坐标 5、依次输入四个格角点的坐标 6、点击【变换】按钮&#xff0c;选择【一阶多项式&#xff08;仿射&#xff09;】变换 7…

基于SpringBoot+定时任务实现地图上绘制车辆实时运动轨迹图

目录 1. 项目结构 2. Maven依赖配置 (pom.xml) 3. 实现后端服务 4. 配置文件 (application.properties) 5. 启动项目 6. 访问页面 实现基于北斗卫星的车辆定位和轨迹图的Maven工程&#xff08;使用模拟数据&#xff09;&#xff0c;我们将使用以下技术&#xff1a; Spri…

使用c#制作一个小型桌面程序

封装dll 首先使用visual stdio 创建Dll新项目,然后属性管理器导入自己的工程属性表&#xff08;如果没有可以参考visual stdio 如何配置opencv等其他环境&#xff09; 创建完成后 系统会自动生成一些文件&#xff0c;其中 pch.cpp 先不要修改&#xff0c;pch.h中先导入自己需…

蓝牙模块—BLE-CC41-A

1. 蓝牙的特点 蓝牙模块采用的 TI 公司设计的 CC2541芯片&#xff0c;主要面向低功耗蓝牙通信方案&#xff0c;该模块的工作频段为 2.4Ghz&#xff0c;这个频段属于国际通用频段 注意&#xff1a;蓝牙集成了一个状态指示灯&#xff0c;LED灯如果均匀慢速闪烁&#xff0c;就表示…

【渗透测试】-vulnhub源码框架漏洞-Os-hackNos-1

vulnhub源码框架漏洞中的CVE-2018-7600-Drupal 7.57 文章目录  前言 1.靶场搭建&#xff1a; 2.信息搜集&#xff1a; 主机探测&#xff1a; 端口扫描&#xff1a; 目录扫描&#xff1a; 3.分析&#xff1a; 4.步骤&#xff1a; 1.下载CVE-2018-7600的exp 2.执行exp: 3.写入木…

Docker安装rabbitmq并配置延迟队列

下载rabbitmq镜像 docker pull rabbitmq:management 运行rabbitmq镜像 docker run -id --namerabbitmq -p 5671:5671 -p 5672:5672 -p 4369:4369 -p 15671:15671 -p 15672:15672 -p 25672:25672 -e RABBITMQ_DEFAULT_USERtom -e RABBITMQ_DEFAULT_PASStom rabbitmq:management …

idea上传jar包到nexus

注意&#xff1a;确保idea中项目为maven项目&#xff0c;并且在nexus中已经创建了maven私服。 1、配置pom.xml中推送代码配置 <distributionManagement> <repository> <id>releases</id> <url>http://127.0.0.1:8001/repository/myRelease/<…

Mybatis自定义TypeHandler,直接存储枚举类对象

在这篇文章中&#xff0c;我们已经知道如何使用枚举类直接接受前端的数字类型参数&#xff0c;省去了麻烦的转换。如果数据库需要保存枚举类的code&#xff0c;一般做法也是代码中手动转换&#xff0c;那么能不能通过某种机制&#xff0c;省去转换&#xff0c;达到代码中直接保…

【Unity-UGUI组件拓展】| Image 组件拓展,支持FIlled和Slice功能并存

🎬【Unity-UGUI组件拓展】| Image 组件拓展,支持FIlled和Slice功能并存一、组件介绍二、组件拓展方法三、完整代码💯总结🎬 博客主页:https://xiaoy.blog.csdn.net 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉 🎄 学习专栏推荐:Unity系统学习专栏 🌲 游戏…

博睿谷IT认证-订阅试学习

在这个信息爆炸的时代&#xff0c;拥有一张IT认证证书&#xff0c;就像拿到了职场晋升的通行证。博睿谷&#xff0c;作为IT认证培训的佼佼者&#xff0c;帮你轻松拿下华为、Oracle等热门认证。下面&#xff0c;让我们一起看看博睿谷如何助你一臂之力。 学习时间&#xff0c;你说…

将阮一峰老师的《ES6入门教程》的源码拷贝本地运行和发布

你好同学&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏、评论和关注。 阮一峰老师的《ES6入门教程》应该是很多同学学习 ES6 知识的重要参考吧&#xff0c;应该也有很多同学在看该文档的时候&#xff0c;想知道这个教程的前端源码是怎么实现的&#xff0c;也可能有同学下载…

移动技术开发:ListView水果列表

1 实验名称 ListView水果列表 2 实验目的 掌握自定义ListView控件的实现方法 3 实验源代码 布局文件代码&#xff1a; activity_main.xml: <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.androi…