【Java数据结构】---哈希表

news2024/10/24 17:37:52

乐观学习,乐观生活,才能不断前进啊!!!

我的主页:optimistic_chen

我的专栏:c语言 ,Java

欢迎大家访问~
创作不易,大佬们点赞鼓励下吧~

前言

在顺序结构以及平衡树中,元素对应的关键码与这个元素在电脑中存储的位置没有对应关系,因此,要查找一个元素,必须要经过该元素关键码的多次比较。面对较多的数据,搜索的效率就大大降低了。也就是说: 搜索的效率取决于搜索过程中元素的比较次数。

最理想的搜索方法就是,不经过任何比较,直接从表中得到要搜索的元素

文章目录

  • 前言
  • 哈希的概念
    • 哈希冲突
    • 冲突 避免
    • 设计合理的哈希函数(第一种方法避免)
      • 常用的哈希函数
    • 调节负载因子(第二种方法避免)
    • 冲突 解决
    • 闭散列(第一种方法解决)
      • 线性探测
      • 二次探测
    • 开散列(哈希桶)(第二种方法解决)
  • 与Java类集的关系
  • 使用HashMap,HashSet
  • 完结

哈希的概念

如果构造一种存储结构,通过某种函数,使元素的存储位置它的关键码之间能够建立一一映射的关系,那么在查找时通过该函数可以很快找到该元素。

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

举个例子:

数据集合{1,7,6,4,5,9};

哈希函数设置为:hash(key)=key%capacity;(capacity为存储元素底层空间总大小 != 数组大小)

按照这个哈希函数求得的值,就是这个元素对应要放的下标。

在这里插入图片描述

哈希冲突

那么如果这组数据里面加了一个14,此时,要怎么放呢?

在这里插入图片描述

显然,此时有两个不同的关键字,使用同一个哈希函数,求得了一个相同的存储位置。此时就发生了哈希冲突

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

冲突 避免

既然有冲突,那就要防止冲突的发生。

但是实际上,由于我们哈希表底层数组的容量往往是小于实际要存储的关键字的数量的,这就导致一个问题,冲突的发生是必然的,但我们能做的应该是尽量的降低冲突率

设计合理的哈希函数(第一种方法避免)

设计原则:

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

比如:前面底层数组长度为10,值域在0~9之间就不会冲突:一旦出现值域之外的值,像是14,就会出现冲突。

  1. 哈希函数计算出来的地址能均匀分布在整个空间中
  2. 哈希函数应该比较简单

常用的哈希函数

  1. 直接定制法:取关键字的某个线性函数为散列地址:Hash(Key)= A*Key + B 。适合查找比较小且连续的情况。

优点:简单、均匀
缺点:需要事先知道关键字的分布情况

  1. 除留余数法:设散列表中允许的地址数为m,取一个不大于m,但最接近或者等于m的质数p作为除数

哈希函数:Hash(key) = key% p(p<=m),将关键码转换成哈希地址

  1. 还有平方取中法、折叠法、数学分析法…………

注意:哈希函数设计的越精妙,产生哈希冲突的可能性就越低,但是无法避免哈希冲突(我们平时也不会去设计一个哈希函数,直接用原生的可以了)

调节负载因子(第二种方法避免)

负载因子a = 填入表中的元素个数 / 散列表的长度

在这里插入图片描述
得出结论:当负载因子越大,冲突率越大。

在这里插入图片描述
增加散列表长度,就只能去扩容,Java里面默认负载因子是0.75,也就是说,当负载因子是0.75时,进行扩容

冲突 解决

闭散列(第一种方法解决)

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

像上面出现的14和4冲突,那就可以把14放到4后边的空位置去

如何去找到下一个空位置?

线性探测

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

在这里插入图片描述
但是这种方法有一个缺点 ,那就是删除的时候,不好直接删除。

如果把4删去,那么搜索14时该怎么找呢?

解决办法肯定有,伪删除,删除的下标设置为bool类型,删除后为false。但是,这样一来就会很复杂。

二次探测

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

在这里插入图片描述
闭散列最大的缺陷就是空间利用率比较低,这也是哈希的缺陷。 为解决这个问题出现了开散列。

开散列(哈希桶)(第二种方法解决)

                        数组+链表的形式

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

通常,哈希表的插入、删除、查找时的时间复杂度为O(1)

与Java类集的关系

  1. HashMap 和 HashSet 即 java 中利用哈希表实现的 Map 和 Set
  2. java 中计算哈希值实际上是调用的类的 hashCode 方法,进行 key 的相等性比较是调用 key 的 equals 方法。所以如果要用自定义类作为 HashMap 的 key 或者 HashSet 的值,必须覆写 hashCode 和 equals 方法,而且要做到 equals 相等的对象,hashCode 一定是一致的

使用HashMap,HashSet

pubilc static void main(String[] args){
     HashMap<String,Integer> map=new HashMap<>();
     map.put("axc",3);
     map.put("hello",13);
     map.put("oca",3);
     
     //Key不能重复,天然去重
     HashSet<String> set=new HashSet<>();
     set.put("axc");
     set.put("hello");
     set.put("oca");  
}

与TreeMap、TreeSet一样,HashSet底层也是一个HashMap,而且方法的使用与TreeMap、TreeSet也一样。

HashMap,HashSet不涉及比较,因为他们底层都是数组+链表,不是搜索树

完结

好了,到这里【Java数据结构】部分就已经结束了~
如果这个系列博客对你有帮助的话,可以点一个免费的赞并收藏起来哟~
可以点点关注,避免找不到我~ ,我的主页:optimistic_chen
我们下期不见不散~~Java

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

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

相关文章

littlefs源码分析1-设计思考

1.littlefs设计目的 littlefs 最初是作为一个实验而构建的&#xff0c;目的是在微控制器的环境中了解文件系统设计。目的是&#xff1a;构建一个在不使用无限制内存的情况下对电源丢失和闪存磨损具有弹性的文件系统。 这对嵌入式文件系统littlefs提出了三个主要要求&#xff1…

【Linux】 exit 和 _exit 的区别

在Linux系统中&#xff0c;exit(int status) 和 _exit(int status) 都是用来终止进程的函数&#xff0c;都能通过参数 int status传递一个整型的退出状态码给父进程&#xff0c;但它们之间有一些重要的区别。 1. 头文件不同 exit() 函数定义在 <unistd.h> 中 _exit() 函…

【Python爬虫实战】高效解析和操作XML/HTML的实用指南

&#x1f308;个人主页&#xff1a;https://blog.csdn.net/2401_86688088?typeblog &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、lxml的安装 &#xff08;一&#xff09;使用 pip 安装 &#xff08;二&…

(一)ubuntu下通过c++编译cpu版本paddleocr-2.8.1

编译环境 操作系统&#xff1a;ubuntu 20.04/22.04 OCR版本&#xff1a;paddleocr 2.8.1 Opencv版本&#xff1a;opencv3.4.16/4.10.0 o参照官方文档&#xff1a; PaddleOCR/deploy/cpp_infer/readme_ch.md at release/2.6 PaddlePaddle/PaddleOCR GitHubhttps://github…

Vue3脚手架和指令

什么是Vue&#xff1f; 简单来说&#xff0c;vue就是可以让有写代码很爽的体验。 概念&#xff1a;Vue是一套构建用户界面的渐进式JavaScript框架。 什么是构建用户界面&#xff1f; 基于数据渲染出用户可以看到的界面 什么是渐进式&#xff1f; 渐进式就是循序渐进的学习…

LabVIEW提高开发效率技巧----VI继承与重载

在LabVIEW开发中&#xff0c;继承和重载是面向对象编程&#xff08;OOP&#xff09;中的重要概念。通过合理运用继承与重载&#xff0c;不仅能提高代码的复用性和灵活性&#xff0c;还能减少开发时间和维护成本。下面从多个角度介绍如何在LabVIEW中使用继承和重载&#xff0c;并…

HttpURLConnection构造请求体传文件

HttpURLConnection构造请求体传文件 在Java中&#xff0c;使用HttpURLConnection构造请求体传输文件&#xff0c;你需要做以下几步&#xff1a; 1、创建URL对象指向你想要请求的资源。 2、通过URL打开连接&#xff0c;转换为HttpURLConnection实例。 3、设置请求方法为POST。 …

Java 多线程(五)—— 阻塞队列、wait、notify

wait wait 和 notify 都是 Object 类提供的方法&#xff0c;也就是说 Java 任意对象都可以使用 这两个方法。 首先 wait 会抛出 InterruptedException 这个异常&#xff0c;说明这个方法可以被 interrupt 给唤醒。 然后我们是不能直接使用 wait 方法的&#xff0c;否则还会抛…

Win10系统安装docker操作步骤

Docker下载 docker下载地址&#xff1a;Docker: Accelerated Container Application Development 打开网页后&#xff0c;点击图下所示&#xff0c;下载windows版本的docker 启用Hyper-V 和容器特性 右键左下角windows图标&#xff0c;选择应用和功能 然后在下面的界面中&am…

电脑技巧:Rufus——最佳USB启动盘制作工具指南

目录 一、功能强大&#xff0c;兼容性广泛 二、界面友好&#xff0c;操作简便 三、快速高效&#xff0c;高度可定制 四、安全可靠&#xff0c;社区活跃 在日常的电脑使用中&#xff0c;无论是为了安装操作系统、修复系统故障还是进行其他需要可引导媒体的任务&#xff0c;拥…

初始JavaEE篇——多线程(2):join的用法、线程安全问题

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;JavaEE 目录 模拟实现线程中断 join的用法 线程的状态 NEW&#xff1a; RUNNABLE&#xff1a; TIMED_WAITING&#xff1a; TERMINATED…

ElasticSearch-7.17.10集群升级至ElasticSearch-7.17.24

文章目录 集群概览 主机名系统版本es01CentOS_7.6-aaarch64ElasticSearch-7.17.10es02CentOS_7.6-aaarch64ElasticSearch-7.17.10es03CentOS_7.6-aaarch64ElasticSearch-7.17.10 需求 1. 将三台ES节点从ElasticSearch-7.17.10升级至ElasticSearch-7.17.24&#xff1b; 2. 保证…

1212,查询球队积分

查询球队积分 表: Teams ------------------------- | Column Name | Type | ------------------------- | team_id | int | | team_name | varchar | ------------------------- team_id 是该表具有唯一值的列。 表中的每一行都代表一支独立足球队。表…

HarmonyOS 模块化设计

1.HarmonyOS 模块化设计 模块化设计文档   应用程序包开发与使用文档 1.1. 概述 组件化一直是移动端比较流行的开发方式&#xff0c;有着编译运行快&#xff0c;业务逻辑分明&#xff0c;任务划分清晰等优点&#xff0c;HarmonyOs组件化的使用&#xff0c;有利于模块之间的解…

【WRF数据准备】地形-SRTM的3s高分辨率地形数据集

【WRF数据准备】地形-SRTM的3s高分辨率地形数据集 数据概述数据下载 数据处理合并多个SRTM 数据-GDAL库转为geogrid二进制格式WPS 中的设置 数据对比海洋区域缺省值参考 WRF中地形数据&#xff08;海拔高度&#xff09;分辨率最高为30s&#xff0c;差不多就是900 m&#xff0c;…

CST光子晶体微谐振腔分析和Q值提取

本期介绍基于文献[1]的一种二维光子晶体波导结构&#xff0c;利用路径上加微谐振腔来实现一些特殊的滤波功能。一般是要看谐振频率的变化和Q值变化&#xff0c;因为工艺误差或任何造成结构不规则的因素对这样细小的结构谐振来说影响非常大。下图为文献中提到的硅薄膜结构&#…

使用Jenkins持续集成的一些经验总结!

01、Performance插件兼容性问题 自由风格项目中&#xff0c;有使用 Performance 插件收集构建产物&#xff0c;但是截至到目前最新版本&#xff08;Jenkins v2.298&#xff0c;Performance&#xff1a;v3.19&#xff09;&#xff0c;此插件和Jenkins都存在有兼容性问题&#x…

业余时间试一试利用AI 人工智能赚钱

内容创作与写作&#xff1a; 撰写文章&#xff1a;许多网站、博客和企业都需要大量的优质内容。利用 AI 工具如 ChatGPT 等&#xff0c;获取文章的思路、框架甚至初稿&#xff0c;然后根据自己的知识和经验进行修改、润色和完善。你可以在一些自由撰稿人平台、内容创作平台上承…

autumn是 “秋天”,year是 “年”,那autumn years是什么意思?柯桥商务剑桥英语学习外贸口语

autumn是“秋天”&#xff0c;year是“年”&#xff0c; 那你知道 autumn years 是什么意思&#xff1f; autumn years是什么意思&#xff1f; autumn years 直译为“秋天的15857575376*年”&#xff0c;但这样的理解并不准确&#xff0c;《剑桥辞典》中对这个词组的英文解释…

如何评估检索增强型生成(RAG)应用

RAG&#xff0c;也就是检索增强型生成&#xff0c;是现在大型语言模型&#xff08;LLMs&#xff09;时代里的一个超火的AI框架&#xff0c;比如你知道的ChatGPT。它通过把外面的知识整合进来&#xff0c;让这些模型变得更聪明&#xff0c;能给出更准确、更及时的回答。详见前篇…