数据结构——TreeMap、TreeSet与HashMap、HashSet

news2024/11/15 18:28:13

目录

一、Map

1、定义

2、常用方法

3、注意

二、TreeMap

三、HashMap

1、定义

2、冲突定义

3、冲突避免方法——哈希函数设计

(1)、直接定制法(常用)

(2)、除留余数法(常用)

(3)、平方取中法

(4)、折叠法

(5)、随机数法

(6)、数学分析法

5、冲突避免方法——闭散列

(1)、线性探测

(2)、线性探测

6、冲突避免方法——开散列/哈希桶

四、Set

1、定义

2、常用方法

3、注意

五、TreeSet

六、HashSet


一、Map

1、定义

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

 

2、常用方法

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 

3、注意

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

二、TreeMap

里面是一个集合 ,TreeMap的底层代码是一个Map集合接口

Map底层结构       TreeMap 
底层结构      红黑树  
插入/删除/查找时间复杂度    O(1)
是否有序       关于Key有序 
线程安全        不安全
插入/删除/查找区别        需要进行元素比较
比较与覆写    key必须能够比较,否则会抛ClassCastException异常  
应用场景    需要Key有序场景下

三、HashMap

1、定义

不经过任何比较,一次直接从表中得到要搜索的元素。 如果构造一种存储结构,通过某种函
数(hashFunc)使元素的存储位置与它的关键码之间能够建立一一映射的关系,那么在查找时通过该函数可以很快找到该元素。

Set底层结构       HashSet 
底层结构      哈希桶
插入/删除/查找时间复杂度    O(1)
是否有序       不一定有序
线程安全        不安全
插入/删除/查找区别        

先计算key哈希地址,然后进行插入和删除

比较与覆写    自定义类型需要覆写equals和hashCode方法
应用场景    key是否有序不关心,需要更高的时间性能

顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关系,查找一个元素时,必须要经过关键码的多次比较。顺序查找时间复杂度为O(N),平衡树中为树的高度,即O(log2N),搜索的效率取决于搜索过程中元素的比较次数。

  • 插入元素:根据待插入元素的关键码,以此函数计算出该元素的存储位置并按此位置进行存放
  • 搜索元素:对元素的关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置取元素比较,若关键码相等,则搜索成功。

 该方式即为哈希(散列)方法,哈希方法中使用的转换函数称为哈希(散列)函数,构造出来的结构称为哈希表(HashTable)(或者称散列表)

2、冲突定义

对于两个数据元素的关键字 和 (i != j),有 != ,但有:Hash( ) == Hash( ),即:不同关键字通过相同哈希哈数计算出相同的哈希地址,该种现象称为哈希冲突或哈希碰撞。把具有不同关键码而具有相同哈希地址的数据元素称为“同义词”。

3、冲突避免方法——哈希函数设计

哈希表底层数组的容量往往是小于实际要存储的关键字的数量的,因此冲突的发生是必然的,所以我们能做的应该是尽量的降低冲突率。

  • 哈希函数的定义域必须包括需要存储的全部关键码,而如果散列表允许有m个地址时,其值域必须在0到m-1之间
  • 哈希函数计算出来的地址能均匀分布在整个空间中
  • 哈希函数应该比较简单

(1)、直接定制法(常用)

取关键字的某个线性函数为散列地址:Hash(Key)= A*Key + B 优点:简单、均匀 缺点:需要事先知道关键字的分布情况 使用场景:适合查找比较小且连续的情况 面试题:字符串中第一个只出现一次字符

(2)、除留余数法(常用)

设散列表中允许的地址数为m,取一个不大于m,但最接近或者等于m的质数p作为除数,按照哈希函数:Hash(key) = key% p(p<=m),将关键码转换成哈希地址

(3)、平方取中法

假设关键字为1234,对它平方就是1522756,抽取中间的3位227作为哈希地址; 再比如关键字为4321,对它平方就是18671041,抽取中间的3位671(或710)作为哈希地址 平方取中法比较适合:不知道关键字的分布,而位数又不是很大的情况

(4)、折叠法

折叠法是将关键字从左到右分割成位数相等的几部分(最后一部分位数可以短些),然后将这几部分叠加求和,并按散列表表长,取后几位作为散列地址。折叠法适合事先不需要知道关键字的分布,适合关键字位数比较多的情况

(5)、随机数法

选择一个随机函数,取关键字的随机函数值为它的哈希地址,即H(key) = random(key),其中random为随机数函数。通常应用于关键字长度不等时采用此法

(6)、数学分析法

设有n个d位数,每一位可能有r种不同的符号,这r种不同的符号在各位上出现的频率不一定相同,可能在某些位上分布比较均匀,每种符号出现的机会均等,在某些位上分布不均匀只有某几种符号经常出现。可根据散列表的大小,选择其中各种符号分布均匀的若干位作为散列地址。

数字分析法通常适合处理关键字位数比较大的情况,如果事先知道关键字的分布且关键字的若干位分布较均匀的情况
注意:哈希函数设计的越精妙,产生哈希冲突的可能性就越低,但是无法避免哈希冲突

5、冲突避免方法——闭散列

闭散列:也叫开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以把key存放到冲突位置中的“下一个” 空位置中去。那如何寻找下一个空位置呢?

(1)、线性探测

比如上面的场景,现在需要插入元素44,先通过哈希函数计算哈希地址,下标为4,因此44理论上应该插在该位置,但是该位置已经放了值为4的元素,即发生哈希冲突。
线性探测:从发生冲突的位置开始,依次向后探测,直到寻找到下一个空位置为止。
插入

  • 通过哈希函数获取待插入元素在哈希表中的位置
  • 如果该位置中没有元素则直接插入新元素,如果该位置中有元素发生哈希冲突,使用线性探测找到下一个空位置,插入新元素
  • 采用闭散列处理哈希冲突时,不能随便物理删除哈希表中已有的元素,若直接删除元素会影响其他元素的搜索。比如删除元素4,如果直接删除掉,44查找起来可能会受影响。因此线性探测采用标记的伪删除法来删除一个元素。

(2)、线性探测

线性探测的缺陷是产生冲突的数据堆积在一块,这与其找下一个空位置有关系,因为找空位置的方式就是挨着往后逐个去找,因此二次探测为了避免该问题,找下一个空位置的方法为:Hi=(H0+i^2)%m,或者:Hi=(H0-i^2)%m。其中i,2,3...,H0是通过散列函数Hash(x)对元素的关键码key进行计算得到的位置,m是表的大小。

因此:比散列最大的缺陷就是空间利用率比较低,这也是哈希的缺陷

6、冲突避免方法——开散列/哈希桶

开散列法又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。

开散列中每个桶中放的都是发生哈希冲突的元素,开散列,可以认为是把一个在大集合中的搜索问题转化为在小集合中做搜索了
 

四、Set

1、定义

Set是继承自Collection的一个接口类,Set中只存储了key,并且要求key一定要唯一。Set最大的功能就是对集合中的元素进行去重

 

2、常用方法

    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中,可以达到去重的效果

3、注意

  • TreeSet的底层是使用Map来实现的,其使用key与Object的一个默认对象作为键值对插入到Map中的
  • 实现Set接口的常用类有TreeSet和HashSet,还有一个LinkedHashSet,LinkedHashSet是在HashSet的基础上维护了一个双向链表来记录元素的插入次序。
  • Set中的Key不能修改,如果要修改,先将原来的删除掉,然后再重新插入
  • TreeSet中不能插入null的key,HashSet可以。
  • TreeSet和HashSet的区别

五、TreeSet

TreeSet的底层是TreeMap,去掉重复的元素,key的重复不会再搜索树中出现

TreeSet继承了Set,Set又继承了Collection

Set底层结构       TreeMap 
底层结构      红黑树  
插入/删除/查找时间复杂度    O(log2N)
是否有序       关于Key有序 
线程安全        不安全
插入/删除/查找区别        

按照红黑树的特性来进行插入和删除

比较与覆写    key必须能够比较,否则会抛出ClassCastException异常
应用场景    需要Key有序场景下

注:

将Map与Set联系起来Set<Map.Entry<String,Integer>> entries=map.entrySet();才能使用Iterable中迭代打印,foreach打印等方法,Map一系中是独立出来并没有实现在下面的关系图中,TreeSet弥补了当前的缺陷。

六、HashSet

Set底层结构       HashSet 
底层结构      哈希桶
插入/删除/查找时间复杂度    O(1)
是否有序       不一定有序
线程安全        不安全
插入/删除/查找区别        

先计算key哈希地址,然后进行插入和删除

比较与覆写    自定义类型需要覆写equals和hashCode方法
应用场景    key是否有序不关心,需要更高的时间性能

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

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

相关文章

kubectl命令控制远程k8s集群(Windows系统、Ubuntu系统、Centos系统)

文章目录1. 本地是linux2. 本地是Windows1. 本地是linux 安装kubectl命令 法一&#xff1a;从master的/usr/bin目录下拷贝kubectl文件到本机/usr/bin目录下法二&#xff1a;GitHub下载kubectl文件 在家目录下创建.kube目录config文件 法一&#xff1a;将master上对应用户的~/.…

binlog、redolog、undolog

目录 一、binlong 1、binlog介绍 作用 特点 2、日志格式 3、写入流程 二、redo log 1、redo log作用 2、redo log如何写入 3、怎么提交数据进行刷盘 4、奔溃恢复流程 三、undolog 一、binlong 1、binlog介绍 作用 binlog是 mysql server 层的一种二进制日志&…

GA-PEG-GA,Glutaric Acid-PEG-Glutaric Acid,戊二酸-聚乙二醇-戊二酸供应

英文名称&#xff1a;Glutaric Acid-PEG-Glutaric Acid&#xff0c;GA-PEG-GA 中文名称&#xff1a;戊二酸-聚乙二醇-戊二酸 GA-PEG-GA是一种线性双功能PEG羧酸试剂。PEG和羧基COOH之间存在C4酯键。PEG羧酸可用于与氨基反应&#xff0c;与NHS和DCC、EDC等肽偶联试剂反应。 P…

CUDA原子操作|参加CUDA线上训练营

什么是原子操作 CUDA的原子操作可以理解为对一个Global memory或Shared memory中变 “读取-修改-写入” 这三个操作的一个最小单位的执行过程&#xff0c;在它执量进行行过程中&#xff0c;不允许其他并行线程对该变量进行读取和写入的操作。 基于这个机制&#xff0c;原子操…

实测2023款哪吒U-II,智驾功能对女司机很友好

最近&#xff0c;我们受邀试驾了2023款哪吒U-II。这是一款A级新能源SUV&#xff0c;是哪吒U的改款车型。哪吒U系列自2020年3月上市到2023年1月&#xff0c;累计销售数量达76688台&#xff0c;也因此被称为15万级智能天花板。2023款哪吒U-II的一大亮点是&#xff1a;针对以往哪吒…

react基础,操作属性样式事件。事件处理this指向问题,及案例

1.1 React 起源于 Facebook 于2013年5月开源. 是一个用于构建用户界面的 JavaScript 库, 与vue,angular并称前端三大框架&#xff0c;现在最新版本是18 特点&#xff1a;-数据驱动&#xff08;操作数据&#xff09; - 组件化 - 虚拟DOM 开发环境&#xff1a; cdn引入js <…

Theano教程:Python的内存管理

在写大型程序时候的一大挑战是如何保证最少的内存使用率。但是在Python中的内存管理是比较简单的。Python显示分配内存&#xff0c;使用引用计数系统管理对象&#xff0c;当指向某一个对象的引用数变为 0 的时候&#xff0c;该对象所占的内存就会被释放。理论上听起来很不错&am…

Linux基础语法进阶版

Linux基础语法 查看文件内容指令 touch 主要是修改文件时间&#xff0c;多用创建文件 -a #只更改访问时间 -m #只更改修改时间 -c --no-create#不创建任何文件cat 展示小文件内容 -b #对于非空输出行编号 -n #对于所有行输出编号 -E #在每行结束处显示"$" -A #展示所…

全国重点城市春节商圈客流数据来了,最火爆商圈果然是它 | 数说热点

作为疫情防控政策进一步放开后的首个春节&#xff0c;在“返乡潮”、“出游潮”和各地促销费政策的刺激下&#xff0c;火热强劲且亮点纷呈的线下消费市场随烟火气再次回归。那么2023年春节&#xff0c;线下消费市场呈现出哪些特点&#xff1f;全国各大购物中心在引客流聚人气方…

Java开发学习(五十)----MyBatisPlus快速开发之代码生成器解析

1、代码生成器原理分析 造句: 我们可以往空白内容进行填词造句&#xff0c;比如: 在比如: 观察我们之前写的代码&#xff0c;会发现其中也会有很多重复内容&#xff0c;比如: 那我们就想&#xff0c;如果我想做一个Book模块的开发&#xff0c;是不是只需要将红色部分的内容全部…

uni-app②

文章目录二、微信小程序简介&#xff08;一&#xff09;文档相关开发者工具使用小程序代码构成小程序基本操作三、uniapp 开发规范uniapp 开发环境开发工具下载 HBuilderX工程搭建项目运行浏览器运行四、组件基础组件基础组件列表组件公共属性集合扩展组件自定义组件UNI-ICON五…

MyBatis笔记【JavaEE】

1.MyBatis是什么 持久层框架 【也是一个ORM框架 对象关系映射】 是一个优秀的ORM持久层框架 特点&#xff1a;灵活 支持自定义SQL、存储过程以及高级映射。MyBatis去除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。MyBatis可以通过简单的XML或注解来配置和映射原始类…

分布式缓存服务DCS-企业版性能更强,稳定性更高

背景介绍 近年来&#xff0c;随着各行业业务需求急速增加&#xff0c;数据量和并发访问量呈指数级增长&#xff0c;原来只能依附于关系型数据库的传统“缓存”逐渐难以支撑上层业务&#xff0c;开源Redis也面临着如“容量有限”、 “可靠性有限”、 “数据重复拷贝&#xff0c…

GeniE 实用教程(二)几何与网格

目 录一、前言二、Guiding Geometry2.1 Guide Point2.2 Guide Line2.3 Guide Plane2.4 Polyline三、Structure3.1 结构梁3.2 结构板3.1 结构壳四、Mesh4.1 网格属性4.2 网格划分4.3 查看网格五、参考文献一、前言 SESAM &#xff08;Super Element Structure Analysis Module&a…

操作系统(day08)内存

存储单元 内存的几个基本概念 存储单元 内存地址从0开始&#xff0c;每个地址对应一个存储单元 存储单元大小根据计算机按照什么方式编址 按字节编址 则每个存储单元大小为一字节&#xff0c;即1B&#xff0c;即8个二进制位按字编址 看这个计算的字长是多少位&#xff0c;如…

一到重要时刻就大脑空白?

很多人可能都经历过这样一幕&#xff1a;花了好多精力准备的一场考试、面试、演讲&#xff0c;到了上场的那一刻&#xff0c;之前准备的东西全都忘了&#xff0c;大脑一片空白。为什么会这样呢&#xff1f;我们所学到的东西都要经过三个步骤才能成为记忆&#xff1a;获取&#…

Leetcode 每日一题 1234. 替换子串得到平衡字符串

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法......感兴趣就关注我吧&#xff01;你定不会失望。 &#x1f308;个人主页&#xff1a;主页链接 &#x1f308;算法专栏&#xff1a;专栏链接 我会一直往里填充内容哒&#xff01; &…

深入解析golang几种非常主流的依赖注入框架,附实现案例及原理解析

什么是依赖注入&#xff1f; 依赖注入 &#xff0c;英文全名是 dependency injection&#xff0c;简写为 DI。 百科解释&#xff1a; 依赖注入是指程序运行过程中&#xff0c;如果需要调用另一个对象协助时&#xff0c;无须在代码中创建被调用者&#xff0c;而是依赖于外部的注…

【情人节专属】AI一键预测你和Ta的CP值

如何预测你和心仪的Ta有没有夫妻相&#xff1f;基于华为云ModelArts开发的【一键预测你和Ta的CP值】Demo帮你预测CP指数。该模型利用ssim算法综合计算五官特征相似程度&#xff0c;从而得出CP值。//夫妻相的原理在当今心理学、生物学仍有很大争议&#xff0c;夫妻相指数高并不意…

nVisual综合布线可视化管理系统解决方案

​一、综合布线管理系统的必要性 如今企事业单位办公人员变化很快&#xff0c;如果还是采用传统方式通过工程竣工图或者网络拓扑图来进行网络维护工作会非常麻烦&#xff0c;并且对管理人员的要求也会很高&#xff0c;管理人员需要清楚的知道工作区的信息点与配线架点之间的对…