数据结构_Map和Set

目录

一、搜索模型

二、Map

2.1 Map.Entry

2.2 Map 方法

2.3 Map 注意事项

三、Set

3.1 Set 方法

3.2 Set 注意事项

四、哈希表

4.1 哈希表

4.2 冲突

4.3 哈希函数设计

4.4 闭散列

4.5 开散列/哈希桶

总结


【搜索树】

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

1、若它的左子树不为空,则左子树上所有节点的值都小于根节点的值。

2、若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。

3、它的左右子树也分别为二叉搜索树。


一、搜索模型

搜索的数据称为关键字 (Key),关键字对应的称为值 (Value),将其称之为键值对 (Key-Value)

1、纯 Key 模型

例如:有一个英文词典,查找一个单词是否在词典中。

2、Key-Value 模型

例如:有一个文件,统计文件中每个单词出现的次数,统计结果是每个单词都有与其对应的次数:<单词,单词出现的次数>。

MapSet 是一种专门用来进行动态搜索的数据结构,其搜索的效率与其具体的实例化子类有关。Map 中存储的就是 Key-Value,而 Set 中只存储了 Key。


二、Map

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

2.1 Map.Entry

Map.Entry<K,V> 是 Map 内部实现的用来存放 <key,value> 键值对映射关系的内部类,可以理解为一个存放键值对的容器。

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

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


2.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

2.3 Map 注意事项

1、Map 是一个接口,不能直接实例化对象,如果要实例化对象只能实例化其实现类TreeMap 或者 HashMap

2、Map 中存放键值对的 key 是唯一的,value 是可以重复的

3、在 TreeMap 中插入键值对时,key 不能为空,否则就会抛 NullPointerException 异常,value 可以为空。但是 HashMap 的 key 和 value 都可以为空。

4、Map 中的 key 可以全部分离出来,存储到 Set 中来进行访问 (因为Key不能重复)。

5、Map 中的 value 可以全部分离出来,存储在 Collection 的任何一个子集合中 (value可能有重复)。

6、Map 中键值对的 key 不能直接修改,value 可以修改,如果要修改 key,需先删除再重新插入。

【TreeMap 和 HashMap 的区别】

Map底层结构 TreeMapHashMap
底层结构红黑树哈希桶
插入/删除/查找时间复杂度O(\log_{2}N)O(1)
是否有序关于Key有序无序
线程安全不安全不安全
插入/删除/查找区别需要进行元素比较通过哈希函数计算哈希地址
比较与覆写key 必须能够比较,否则会抛出  ClassCastException 异常自定义类型需要覆写 equals 和  hashCode 方法
应用场景需要 Key 有序场景下Key 是否有序不关心,需要更高的时间性能

三、Set

Set 与 Map 主要的不同有两点:

1、Set 是继承自 Collection 的接口。

2、Set 中只存储了 Key。

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

3.2 Set 注意事项

1、Set 是继承自 Collection 的一个接口类。

2、Set 中只存储了 key,并且要求 key 一定要唯一

3、TreeSet 的底层是使用 Map 来实现的,其使用 key 与 Object 的一个默认对象作为键值对插入到 Map 中的。

4、Set 最大的功能就是对集合中的元素进行去重

5、实现 Set 接口的常用类有 TreeSetHashSet,还有一个 LinkedHashSet,LinkedHashSet 是在 HashSet 的基础上维护了一个双向链表来记录元素的插入次序。

6、Set 中的 Key 不能修改,如果要修改,需删除后重新插入。

7、TreeSet 中不能插入 null 的 key,HashSet 可以。

【TreeSet 和 HashSet 的区别】

Set底层结构 TreeSetHashSet
底层结构红黑树哈希桶
插入/删除/查找时间复杂度O(\log_{2}N)O(1)
是否有序关于 Key 有序不一定有序
线程安全不安全不安全
插入/删除/查找区别按照红黑树的特性通过哈希函数计算哈希地址
比较与覆写key 必须能够比较,否则会抛出  ClassCastException 异常自定义类型需要覆写 equals 和  hashCode 方法
应用场景需要 Key 有序场景下Key 是否有序不关心,需要更高的时间性能

四、哈希表

4.1 哈希表

哈希(散列)方法可以通过哈希(散列)函数使元素的存储位置与它的关键码之间建立一一映射的关系,构造出哈希表(散列表)。哈希表可以在查找时不经过任何比较,一次直接从表中得到要搜索的元素。

例如:数据集合 {1,5,3,7,6,9};

哈希函数设计为:hash(key) = key % capacity,capacity 为存储元素空间总大小。由此计算出该元素的哈希地址,即可存储该元素。

可以看出,使用哈希方法进行搜索不用进行多次关键码的比较,搜索速度很快。可若往数据集合中插入元素 17,由于 17 % 10 = 7,故元素 7 与元素 17 会产生冲突


4.2 冲突

不同关键字通过相同哈希函数计算出相同的哈希地址,这种现象称为哈希冲突 (哈希碰撞)

把具有不同关键码二具有相同哈希地址的数据元素称为"同义词"。


4.3 哈希函数设计

由于哈希表容量小于实际要存储的关键字数量,所有发生冲突是必然的,我们能做的只是尽量降低冲突率

引起哈希冲突的一个原因:哈希函数设计不够合理,哈希函数设计原则

1、哈希函数的定义域必须包括需要存储的全部关键码,而如果哈希表允许有 m 个地址时,其值域必须在 0 到 m-1 之间。

2、哈希函数计算出来的地址能均匀分布在整个空间中。

3、哈希函数应该比较简单。


【常见哈希函数】

1、直接定制法

取关键字的某个线性函数为哈希地址:hash(Key) = A*key + B。

优点:简单、均匀。

缺点:需要事先知道关键字的分布情况。

使用场景:适合查找比较小且连续的情况。

2、除留余数法

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


【负载因子调节】

哈希表的载荷因子定义为:α = 存入表中的元素个数 / 哈希表的长度。 

α 是哈希表装满程度的标志因子。由于表长是定值,故 α 与 "存入表中的元素个数" 成正比,α 越大,"存入表中的元素个数" 越多,产生冲突的可能性就越大。故为了降低冲突率,当 α 达到一定程度时,我们需要扩容 "哈希表的长度"。例如,Java 的系统库中限制了载荷因子为 0.75,超过此值将 resize 哈希表。


解决哈希冲突的两种常见方法是:闭散列开散列


4.4 闭散列

闭散列,也叫开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以把 key 存放到冲突位置中的"下一个"空位置中去。故又有了两种方法将冲突的元素存至其他位置。

1、线性探测

从发生冲突的位置开始,依次向后探测,直到寻找到下一个空位置为止。

例如上文中,需要再插入元素 17,此时通过哈希函数计算出哈希地址为 7,但发生了哈希冲突。故用到线性探测,寻找到下标 8 为空,存入元素 17。

若再插入元素 27,即继续线性探测,寻找到下标 0 为空,存入元素 27。

2、二次探测

线性探测的缺陷是产生冲突的数据堆积在一块,因此二次探测为了避免该问题,找"下一个"空位置的方法为:,其中 i = 1,2,3,……是通过哈希函数计算得到的哈希地址m表的大小

故若插入元素 17 发生哈希冲突,使用二次探测

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

4.5 开散列/哈希桶

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

从上图可以看出,开散列每个桶中放的都是发生哈希冲突的元素。此时插入元素 17 和 27 会得到:

开散列,可以理解为把一个在大集合中的搜索问题转化为在小集合中的搜索。


【哈希表时间复杂度】

虽然哈希表一直在和冲突做斗争,但在实际使用过程中,我们认为哈希表的冲突率是不高的,冲突个数是可控的,也就是每个桶中的链表的长度是一个常数,所以,通常意义下,我们认为哈希表的插入/删除/查找时间复杂度是 O(1)


总结

1、Map 和 Set 是一种专门用来进行动态搜索的数据结构。

2、Map 中存储的就是 Key-Value,而 Set 中只存储了 Key。

3、不同关键字通过相同哈希函数计算出相同的哈希地址,这种现象称为哈希冲突 (哈希碰撞)。

4、开散列中每个桶中放的都是发生哈希冲突的元素。

5、哈希表的插入/删除/查找时间复杂度是 O(1)。

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

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

相关文章

spring-boot 整合 redisson 实现延时队列(文末有彩蛋)

应用场景 通常在一些需要经历一段时间或者到达某个指定时间节点才会执行的功能&#xff0c;比如以下这些场景&#xff1a; 订单超时提醒收货自动确认会议提醒代办事项提醒 为什么使用延时队列 对于数据量小且实时性要求不高的需求来说&#xff0c;最简单的方法就是定时扫描数据…

语音合成-TTS文字转语音(专业版)

语音合成-TTS文字转语音(专业版) 一、工具简介 *使用强大的智能AI语音库&#xff0c;合成独具特色接近真人语音的朗读音频。 *使用极具表现力和类似人类的声音&#xff0c;使文本阅读器和已启用语音的助理等方案栩栩如生。 *用途&#xff1a;这个语音工具&#xff0c;不仅可…

【C语言初阶】C语言数组基础:从定义到遍历的全面指南

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C语言 “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;C语言函数 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀数组 &#x1f4d2;1. 什么是数组…

【C++】学习笔记——AVL树

文章目录 十六、AVL树1. AVL树的概念2. AVL树节点的定义3. AVL树的插入4. AVL树的旋转5. AVL树的验证6. 完整代码测试7. AVL树的性能 未完待续 十六、AVL树 1. AVL树的概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索树将退化为单支树&…

前端基础之JavaScript学习——函数的使用

大家好我是来自CSDN的前端寄术区博主PleaSure乐事&#xff0c;今天我们继续有关JavaScript的学习&#xff0c;使用的编译器为vscode&#xff0c;浏览器为谷歌浏览器。 函数的声明与使用 声明 在JavaScript当中函数的声明和其他语言类似&#xff0c;使用如下格式即可声明&…

实战篇(十):使用Processing创建可爱花朵:实现随机位置、大小和颜色的花朵

使用Processing创建可爱花朵 0.效果预览1. 引言2. 设置Processing环境3. 创建花朵类4. 实现花瓣绘制5. 绘制可爱的笑脸6. 鼠标点击生成花朵7. 完整代码8. 总结与扩展0.效果预览 在本教程中,我们将使用Processing编程语言来创建一个可爱的花朵生成器。通过封装花朵为一个类,并…

大语言模型-检索测评指标

1. MRR &#xff08;Mean Reciprocal Rank&#xff09;平均倒数排名&#xff1a; 衡量检索结果排序质量的指标。 计算方式&#xff1a; 对于每个查询&#xff0c;计算被正确检索的文档的最高排名的倒数的平均值&#xff0c;再对所有查询的平均值取均值。 意义&#xff1a; 衡量…

【STM32】按键控制LED光敏传感器控制蜂鸣器(江科大)

一、按键控制LED LED.c #include "stm32f10x.h" // Device header/*** 函 数&#xff1a;LED初始化* 参 数&#xff1a;无* 返 回 值&#xff1a;无*/ void LED_Init(void) {/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENAB…

199.二叉树的右视图(DFS)

给定一个二叉树的根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4] 示例 2: 输入: [1,null,3] 输出: [1,3] 示例 3: 输入: [] 输出: [] 解题…

贪心算法总结(1)

一、贪心算法简介 常用方法&#xff1a;交换论证法、数学归纳法、反证法、分类讨论 二、柠檬水找零&#xff08;交换论证法&#xff09; . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:bool lemonadeChange(vector<int>& bills) {int five0,t…

【考研数学】线代满分经验分享+备考复盘

我一战二战复习都听了李永乐的线代课&#xff0c;二战的时候只听了一遍强化&#xff0c;个人感觉没有很乱&#xff0c;永乐大帝的课逻辑还是很清晰的。 以下是我听向量这一章后根据听课内容和讲义例题总结的部分思维导图&#xff0c;永乐大帝讲课的时候也会特意点到线代前后联…

TK秘籍:深度剖析机房IP与住宅IP的利与弊

大家好&#xff0c;今天我们来聊聊TikTok运营中的一个重要环节——IP地址的选择。 想象一下&#xff0c;你在TikTok上发布视频&#xff0c;就像是在一个热闹的市集上摆摊&#xff0c;而IP地址就是你的摊位位置。选对了位置&#xff0c;你的摊位就能吸引更多顾客&#xff0c;也…

最小二乘求待定位点的位置(三维环境)|MATLAB

前言 之前发过三点法求待测点位置的程序讲解&#xff0c;哪个是二维的&#xff0c;见&#xff1a;基于伪逆的三点法距离求位置&#xff0c;MATLAB源代码&#xff08;MATLAB函数&#xff09; 这里给出三维情况下的函数和测试代码。对于函数&#xff0c;输入已知锚点的位置、待…

JavaEE:Spring Web简单小项目实践三(留言板实现)

学习目的&#xff1a; 1、理解前后端交互过程 2、学习接口传参&#xff0c;数据返回以及页面展示 目录 1、准备工作 2、约定前后端交互接口 1、获取全部留言 2、发表新留言 3、实现服务器端代码 4、调整前端页面代码 5、运行测试 1、准备工作 创建SpringBoot项目&#x…

Linux 服务器管理和维护

Linux 是一个非常严谨的操作系统&#xff0c;每个目录都有自己的作用&#xff0c;这些作用是固定的&#xff0c;没有特殊情况&#xff0c;应严格执行&#xff1b; Linux 中所有东西以文件形式存储和管理&#xff0c;命令也不例外&#xff1b; 以下四个 bin 是二进制文件&…

SVM 技能测试:25 个 MCQ 用于测试数据科学家的 SVM

SVM 技能测试:25 个 MCQ 用于测试数据科学家的 SVM(2024 年更新) 一、介绍 你可以把机器学习算法想象成一个装满斧头、剑和刀片的军械库。你有各种各样的工具,但你应该学会在正确的时间使用它们。打个比方,将“线性回归或逻辑回归”视为一把能够有效地切片和切块数据但…

LeetCode 739, 82, 106

文章目录 739. 每日温度题目链接标签思路代码 82. 删除排序链表中的重复元素 II题目链接标签思路代码 106. 从中序与后序遍历序列构造二叉树题目链接标签思路二叉树的三种遍历值与索引的映射对于后序遍历的使用对于中序遍历的使用 代码 739. 每日温度 题目链接 739. 每日温度…

jenkins 插件版本冲突

一、Jenkins安装git parameter 插件重启后报错与临时解决方案 cd /root/.jenkins cp config.xml config.xml.bak vim config.xml <authorizationStrategy class"hudson.security.FullControlOnceLoggedInAuthorizationStrategy"><denyAnonymousReadAcces…

【工具使用】EMACS的verilog_mode脚本

#工作记录# 俗话说不会玩连连看的工程师不是一个好的SoC工程师。 在做集成工作的时候&#xff0c;集成连线估计是一件比较繁琐且容易出错的事情&#xff0c;连线类型定义出错、位宽问题、连线众多等等问题&#xff0c;此时使用由Veripool带来的verilog_mode简直是令人神清气爽…

基于牛顿-拉夫逊优化算法(Newton-Raphson-based optimizer, NBRO)的无人机三维路径规划

牛顿-拉夫逊优化算法(Newton-Raphson-based optimizer, NBRO)是一种新型的元启发式算法&#xff08;智能优化算法&#xff09;&#xff0c;该成果由Sowmya等人于2024年2月发表在中科院2区Top SCI期刊《Engineering Applications of Artificial Intelligence》上。 1、算法原理…