Java数据结构 | TreeMap 和 TreeSet

TreeMap 和 TreeSet

    • 1. 搜索树
      • 1.1 概念
      • 1.2 搜索树的查找、插入、删除思路及代码
        • 1.2.1 查找
        • 1.2.2 插入
        • 1.2.3 删除(难点)
      • 1.3 二叉搜索树的性能分析
    • 2. Map 和 Set
      • 2.1 Map 接口
        • 2.1.1 Map.Entry<K,V>
        • 2.1.2 Map的常用方法
      • 2.2 Set 接口
        • 2.2.1 Set 的常用方法

TreeMap 和 TreeSet 是 Java 中利用搜索树实现的 Map 和 Set,具体来说是利用的红黑树,红黑树是一棵近似平衡的二叉搜索树,即在二叉树搜索树的基础上添加颜色和红黑树的性质验证。那么什么是搜索树?什么是 Map ?什么是 Set ?

1. 搜索树

1.1 概念

二叉搜索树又称二叉排序树,它或是一棵空树,或是一棵具有以下性质的二叉树:

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  • 它的左右子树也分别是二叉搜索树

如图是根据数组int array = {4,1,3,6,8,7,2,9,0,4} 构建的一棵二叉搜索树
在这里插入图片描述

1.2 搜索树的查找、插入、删除思路及代码

1.2.1 查找

思路: 给定一个要查找的 value 值,让 value 值与根节点进行比较,若 value 值比根节点值大,则去根节点的右子树查找,若 value 值比根节点值小,则去根节点的左子树查找

⭐代码实现:

    public TreeNode search(int val) {//让cur指向根节点TreeNode cur = root;while (cur != null) {if (val > cur.val) {cur = cur.right;//val比根节点的值大,去右子树找} else if (val < cur.val) {cur = cur.left;//val比根节点的值小,去左子树找} else {return cur;//找到了}}return null;}
1.2.2 插入

思路: 插入的思路和查找类似,给定一个要插入的 value 值,让 value 值与根节点的值进行比较,若 value 值比根节点的值大,则去根节点的右子树继续判断;若 value 值比根节点的值小,则去根节点的左子树继续判断;若遇到相同数值,则不插入;若根节点为空。则创建节点将 value 值插入。在写代码时,我们需要定义一个 cur 引用去寻找位置,同时还需要定义一个 parent 引用去记录 cur 所指节点的父亲节点,若不定义 parent 则会丢失插入位置!

图示
⭐代码实现:

    public void insert(int val) {TreeNode newNode = new TreeNode(val);if (root == null) {root = newNode;return;}TreeNode cur = root;TreeNode parent = null;while (cur != null) {parent = cur;if (val > cur.val) {cur = cur.right;} else if (val < cur.val) {cur = cur.left;} else {return;//存在相同数值,不插入}}//走到这里,cur为空了,创建节点if (val > parent.val) {parent.right = newNode;} else {parent.left = newNode;}}
1.2.3 删除(难点)

待删除节点的引用为 cur ,待删除结点的双亲节点为 parent

思路:

  • 情况一:待删除结点的左孩子为空,即 cur.left == null

    • a. cur 是根节点;
    • b. cur 不是根节点,cur == parent.left;
    • c. cur 不是根节点,cur == parent.right;
      情况一
  • 情况二:待删除结点的右孩子为空,即 cur.right == null

    • a. cur 是根节点;
    • b. cur 不是根节点,cur == parent.left;
    • c. cur 不是根节点,cur == parent.right;
      情况二
  • 情况三:待删除结点的左右孩子都不为空,即 cur.left != null && cur.right != null

    • 使用替换法进行删除,在左子树中寻找一个最大值节点或者在右子树中寻找一个最小值节点,与当前 cur 节点替换,再处理节点的删除问题;(以取右子树最小值为例)
      在这里插入图片描述

⭐代码实现:

    //二叉搜索树的删除public void remove(int val) {TreeNode cur = root;TreeNode parent = null;//查找到节点位置while (cur != null) {parent = cur;if (cur.val < val) {cur = cur.right;} else if (cur.val > val) {cur = cur.left;} else {//找到节点,进行删除removeNode(cur,parent);return;}}}private void removeNode(TreeNode cur, TreeNode parent) {if (cur.left == null) {if (cur == root) {root = cur.right;} else if (cur == parent.left) {parent.left = cur.right;} else {parent.right = cur.right;}} else if (cur.right == null) {if (cur == root) {root = cur.left;} else if (cur == parent.left) {parent.left = cur.left;} else {parent.right = cur.left;}} else {//去右子树找最小值节点TreeNode target = cur.right;TreeNode targetParent = cur;//最左边是最小值,所以要找到最左边while (target.left != null) {targetParent = target;target = target.left;}//交换值cur.val = target.val;if (target == targetParent.left) {targetParent.left = target.right;} else {targetParent.right = target.right;}}}

1.3 二叉搜索树的性能分析

要进行二叉搜索树的插入和删除操作都必须进行查找操作,查找效率代表了二叉搜索树中各个操作的性能。
对于同一个关键码集合,如果插入的次序不同,则可能会得到不同结构的二叉搜索树。

最优情况下:二叉搜索树为完全二叉树,平均比较次数为 logN ,查找的时间复杂度为 O(logN)
最差情况下:二叉搜索树退化为单只树,平均比较次数为 N ,查找的时间复杂度为 O(N)

2. Map 和 Set

Map 和 Set 是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关,Map 和 Set 是一种适合动态查找的集合容器。

模型: 一般把搜索的数据称为关键字(Key),和关键字对应的称为值(Value),将其称之为 Key-Value 的键值对,因此模型会有两种:

  • 纯 Key 模型: 比如查找一个单词是否在这篇文章里
  • Key-Value模型: 比如一个单词在在文章中出现的次数

注:Map 中存储的就是 Key-Value 键值对,而 Set 中只存储了 Key

2.1 Map 接口

Map是一个接口类,该类没有继承自 Collection ,该类中存储的是 <K,V> 结构的键值对,K 一定是唯一的,并且不能重复。

2.1.1 Map.Entry<K,V>

Map.Entry<K,V> 是 Map 内部实现的用来存放 <Key,Value> 键值对映射关系的内部类,该内部类中主要提供了 <Key,Value> 的获取,Value 的设置以及 Key 的比较方式。

方法解释
K getKey()返回 entry 中的 key
V getValue()返回 entry 中的 value
VsetValue(V value)将键值对中的 value 替换为指定的 value

注:Map.Entry<K,V> 中没有提供设置 Key 的方法

2.1.2 Map的常用方法
方法解释
V get(Object key)返回 key 对应的 value
V getOrDefault(Object key, V defaultValue)返回 key 对应的 value,key 不存在,返回默认值
V put(K key, V value)设置 key 对应的 value
V remove(Object key)删除 key 对应的映射关系
Set< K > keySet()返回所有 key 的不重复集合
Collection< V > values()返回所有 value 的可重复集合
Set<Map.Entry<K, V>> entrySet()返回所有的 key-value 映射关系
boolean containsKey(Object key)判断是否包含 key
boolean containsValue(Object value)判断是否包含 value

说明:

  1. Map 是一个接口,不能直接实例化对象,如果要实例化对象只能实例化其实现类 TreeMap。
  2. Map 中存放键值对的 Key 是唯一的,value 是可以重复的。
  3. 在 TreeMap 中插入键值对时,key 不能为空,否则就会抛 NullPointerException 异常,value 可以为空。
  4. Map 中的 Key 可以全部分离出来,存储到 Set 中来进行访问 (因为 Key 不能重复) 。
  5. Map 中的 value 可以全部分离出来,存储在 Collection 的任何一个子集合中( value 可能有重复)。
  6. Map 中键值对的 Key 不能直接修改,value 可以修改,如果要修改 key,只能先将该 key 删除掉,然后再来进行重新插入。

2.2 Set 接口

Set 是继承自 Collection 的接口类,Set 中只存储了 Key,并且 Key 唯一

2.2.1 Set 的常用方法
方法解释
boolean add(E e)添加元素,但重复元素不会被添加成功
void clear()清空集合
boolean contains(Object o)判断 o 是否在集合中
Iterator< E > iterator()返回迭代器
boolean remove(Object o)删除集合中的 o
int size()返回set中元素的个数
boolean isEmpty()检测set是否为空,空返回true,否则返回false
Object[] toArray()将set中的元素转换为数组返回
boolean containsAll(Collection<?> c)集合c中的元素是否在set中全部存在,是返回true,否则返回false
boolean addAll(Collection<? extends E> c)将集合c中的元素添加到set中,可以达到去重的效果

说明:

  1. TreeSet 的底层是使用 Map 来实现的,其使用 key 与 Object 的一个默认对象作为键值对插入到 Map 中的。
  2. Set 最大的功能就是对集合中的元素进行去重。
  3. 实现 Set 接口的常用类有 TreeSet 和 HashSet ,还有一个 LinkedHashSet,LinkedHashSet 是在 HashSet 的基础上维护了一个双向链表来记录元素的插入次序。
  4. Set 中的 Key 不能修改,如果要修改,先将原来的删除掉,然后再重新插入。
  5. TreeSet 中不能插入的 key 不能为 null 。

⚠️⚠️⚠️ 注:Map 和 Set 的常用方法需要通过不断的练习进行掌握!!!

TreeMap 和 TreeSet 的内容到这里就结束啦,有任何问题欢迎私信留言一起探讨!
在这里插入图片描述

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

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

相关文章

智能理解 PPT 内容,快速生成讲解视频

当我们想根据一版 PPT 制作出相对应的解锁视频时&#xff0c;从撰写解锁词&#xff0c;录制音频到剪辑视频&#xff0c;每一个环节都需要投入大量的时间和精力&#xff0c;本方案将依托于阿里云函数计算 FC 和百炼模型服务&#xff0c;实现从 PPT 到视频的全自动转换&#xff0…

小鹅通首页网页开发

一、小鹅通首页开发 二、代码&#xff1a; index.html: <!DOCTYPE html><html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title&…

离散型变量的 PSI-群体稳定性指标计算

文章目录 PSI-群体稳定性指标(离散型)单个指标计算所有指标计算 PSI-群体稳定性指标(离散型) 单个指标计算 代码 import pandas as pddf pd.read_csv(/Users/mengzhichao/Desktop/文件/图表/小微企业用电量数据.csv)X_train df.sample(n7000) X_test df.sample(n3000)计算单…

STM32G474--Whetstone程序移植(单精度)笔记

1 准备基本工程代码 参考这篇笔记从我的仓库中选择合适的基本工程&#xff0c;进行程序移植。这里我用的是stm32g474的基本工程。 使用git clone一个指定文件或者目录 2 移植程序 2.1 修改Whetstone.c 主要修改原本变量定义的类型&#xff0c;以及函数接口全部更换为单精度…

【电机控制器】STC8H1K芯片——低功耗

【电机控制器】STC8H1K芯片——低功耗 文章目录 [TOC](文章目录) 前言一、芯片手册说明二、IDLE模式三、PD模式四、PD模式唤醒五、实验验证1.接线2.视频&#xff08;待填&#xff09; 六、参考资料总结 前言 使用工具&#xff1a; 1.STC仿真器烧录器 提示&#xff1a;以下是本…

Neo4j图数据库学习(二)——SpringBoot整合Neo4j

一. 前言 本文介绍如何通过SpringBoot整合Neo4j的方式&#xff0c;对图数据库进行简单的操作。 Neo4j和SpringBoot的知识不再赘述。关于Neo4j的基础知识&#xff0c;有兴趣可以看看作者上一篇的文章&#xff1a;Neo4j图数据库学习(一)——初识CQL 二. 前置准备 新建SpringBo…

【后端开发】系统设计101——Devops,Git与CICD,云服务与云原生,Linux,安全性,案例研究(30张图详解)

【后端开发】系统设计101——Devops&#xff0c;Git与CICD&#xff0c;云服务与云原生&#xff0c;Linux&#xff0c;安全性&#xff0c;案例研究&#xff08;30张图详解&#xff09; 文章目录 1、DevopsDevOps与SRE与平台工程的区别是什么&#xff1f;什么是k8s&#xff08;Ku…

01_Machine Vision_LSI及傅立叶变换

outline 图像分解和线性时不变系统二维傅立叶变换图像采样 图像分解和线性时不变系统 图像数学表达 图像由基本的像素点组成&#xff0c;如果将每一个像素点看作一个脉冲&#xff0c;则每个像素点的值可以看作是脉冲的幅值&#xff0c;这样图像就可以看作是由一系列脉冲组成…

elasticsearch实战三 elasticsearch与mysql数据实时同步

一 介绍 elasticsearch数据不是一直不变的&#xff0c;需要与mysql、oracle等数据库的数据做同步。 本博客里涉及到的项目地址&#xff1a;https://www.aliyundrive.com/s/7bRWpTYsxWV 方案一&#xff1a; 同步调用&#xff0c;即操作mysql数据后&#xff0c;接着操作elastic…

智能化食品安全管理:AI视频监控在大型商场的技术方案

前言 在卖场中&#xff0c;尤其是熟食区&#xff0c;AI视频监控的应用对于食品安全至关重要。通过AI视频监控系统&#xff0c;卖场可以实时监测食品处理环节中的每一个细节&#xff0c;从员工的个人防护到清洁操作&#xff0c;再到区域管理&#xff0c;全面提升食品安全管理的…

分析模式应用――帐务模式02

Party 模式中的层次结构模型支持多种灵活的层次结构&#xff0c;但这里我们只要关心上下级的包含关系就可以了&#xff0c;参加结算的称为结算实体BalanceEntity&#xff0c; 不可再拆分的称为LeafEntity&#xff0c; 可以包含下级结算实体的称为CompositeEntity&#xff0c;因…

什么是网络安全

1) 什么是网络安全 作为程序员&#xff0c;主要是面向产品的安全的问题。比如sql注入&#xff0c;xss&#xff0c;csrf&#xff0c;cookie窃取等等&#xff0c;都值得我们去思考。保证网站运行正常&#xff0c;客户数据安全。 2) sql注入 简单的说&#xff0c;就是利用表单提…

2025年软件测试五大趋势:AI、API安全、云测试等前沿实践

随着软件开发的不断进步&#xff0c;测试方法也在演变。企业需要紧跟新兴趋势&#xff0c;以提升软件质量、提高测试效率&#xff0c;并确保安全性&#xff0c;在竞争激烈的技术环境中保持领先地位。本文将深入探讨2025年最值得关注的五大软件测试趋势。 Parasoft下载https://…

等级保护2.0|网络安全服务

等级保护2.0|网络安全服务 定义 对于国家秘密信息、法人和其他组织及公民专有信息以及公开信息的存储、传输、处理这些信息系统分等级实行安全保护&#xff0c;对信息系统中发生的信息安全时间分等级响应、处置。 思想 对信息安全实行等级化保护和等级化管理 目标 突出重…

Spatial Branching for Conic Non-Convexities in Optimal Electricity-Gas Flow

摘要—本文提出了一种基于几何的空间分支策略&#xff08; spatial branching strategy&#xff09;&#xff0c;用于解决集成电力-燃气系统中的圆锥非凸方程&#xff08; conic non-convex equations&#xff09;。所提出的策略嵌入在空间分支定界算法中&#xff0c;以求解最优…

ChunkKV:优化 KV 缓存压缩,让 LLM 长文本推理更高效

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

IDEA编写SpringBoot项目时使用Lombok报错“找不到符号”的原因和解决

目录 概述|背景 报错解析 解决方法 IDEA配置解决 Pom配置插件解决 概述|背景 报错发生背景&#xff1a;在SpringBoot项目中引入Lombok依赖并使用后出现"找不到符号"的问题。 本文讨论在上述背景下发生的报错原因和解决办法&#xff0c;如果仅为了解决BUG不论原…

【Redis】redis 存储的列表如何分页和检索

博主介绍&#xff1a;✌全网粉丝22W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…

基于SpringBoot的线上历史馆藏管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

Redis持久化机制详解

为什么需要持久化 Redis通常被作为缓存使用&#xff0c;但是Redis一旦宕机&#xff0c;内存中的数据全部丢失&#xff0c;可能会导致数据库崩溃。如果是从数据库中恢复这些数据就会存在频繁访问数据库和读取速度慢的问题。所以redis实现数据的持久化&#xff0c;是至关重要的。…