哈希与哈希表

news2024/11/16 18:07:50

哈希表的概念

哈希表又名散列表,官话一点讲就是:

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。

 —— 摘自百度百科

那么通俗一点讲,哈希表就是一张映射表,通过哈希映射,将关键字映射到哈希表中,使得关键字与哈希值具有一一对应的关系。

图片出处: 算法数据结构基础——哈希表(Hash Table)-CSDN博客

这样我们就可以直接通过找到

哈希函数

哈希函数的一个关键就是通过哈希方法来得到一个映射值,理论上关键字与映射值一一对应。一般来说,哈希方法大致有如下这些:

  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种不同的符号在各位上出现的频率不一定相同,可能在某些位上分布比较均匀,每种符号出现的机会均等,在某些位上分布不均匀只有某几种符号经常出现。可根据散列表的大小,选择其中各种符号分布均匀的若干位作为散列地址。

其中,直接定址法、除留余数法是两种较为常用的哈希方法。而直接定址法有非常多的实现方式比如:各种字符串Hash函数 - clq - 博客园 (cnblogs.com),所以哈希表的大体思路很好理解,但具体实现上却大有讲究。

哈希冲突及其解决方案

不管是哪种哈希方法,随着数据量的增大,必然会造成哈希冲突。哈希冲突就是多个关键字映射的是同一个哈希值的情况。一般来说,解决哈希冲突通常有两种方式:闭散列和开散列。

闭散列 - 开放定址法

简单来说,如果当前哈希映射值对应的位置已经有数据了,就产生了哈希冲突。开放定址法的做法是,再找一个映射位置。常用的有线性探测和二次探测两种方式:

  • 线性探测法:$F(i) = 1, 2, 3, ..., m - 1$。

  • 二次探测法:$F(i) = 1^2, -1^2, 2^2, -2^2, ..., \pm n^2(n \le m / 2)$。

简单来说就是,线性探测在发生哈希冲突之后,线性地向后寻找,直到找到一个空位为止。二次探测是指,第一个在哈希值上加上一个1的平方,如果发生哈希冲突,第二次就减去一个1的平方,第三次加上2的平方,第四次……这样以此类推。那么查找时也是按照对应的探测方式进行查找的。

开散列 - 链地址法(开链法)

而开散列则相对更容易接受一些。开散列又称连地址法,是指的每个哈希表中存放的数据不再是一个单纯的数据,而是一个链表,所有映射值相同的关键字都被这个链表所链起来,就像下面这样:

图片出处: 算法数据结构基础——哈希表(Hash Table)-CSDN博客

注意事项与总结

  1. 哈希表的两个核心内容在于哈希函数与哈希冲突的解决。哈希函数大致有如下这几类:直接定址法、除留余数法、平方取中法、基数转换法、数字分析法、折叠法、随机数法、乘积法、点积法等。哈希冲突的解决常用的有开放地址法和链地址法。
  2. 在哈希表的具体实现中,因为扩容操作会改变哈希的映射关系,所以扩容时每一个元素都需要重新插入。
  3. 在具体实现时,可以通过负载因子(有效值与最大容量的比值)来控制扩容的时机。
  4. 哈希与哈希表的区别是,哈希是一种思想,哈希表是哈希这种思想的一种实现方式,其它的还有比如位图、布隆过滤器等也是哈希思想的一种体现。

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

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

相关文章

MySQL的多表查询

多表关系 一对多(多对一)-> 多对多-> 一对一-> 概述 概述 多表查询分类 内连接 代码演示--> -- 内连接演示 -- 1.查询每一个员工的姓名&#xff0c;及关联的部门的名称(隐式内连接实现) select emp.name, dept.name from emp,dept where emp.dept_id dept.id; …

10、外观模式(Facade Pattern,不常用)

外观模式&#xff08;Facade Pattern&#xff09;也叫作门面模式&#xff0c;通过一个门面&#xff08;Facade&#xff09;向客户端提供一个访问系统的统一接口&#xff0c;客户端无须关心和知晓系统内部各子模块&#xff08;系统&#xff09;之间的复杂关系&#xff0c;其主要…

sql面试题之“互相关注的人”(方法三)

题目&#xff1a;某社交平台有关注这个功能&#xff0c;关注的同时也会被关注。现有需求需要找出平台上哪些用户之间互相关注。 文章目录 题目如下&#xff1a;一、数据准备二、建表并导入数据1.建表2.导入数据3.数据分析和实现思路小结&#xff1a; 题目如下&#xff1a; 某社…

[RK-Linux] 移植Linux-5.10到RK3399(三)| 检查eMMC与SD卡配置

这个专题主要记录把 RK Linux-5.10 移植到 ROC-RK3399-PC Pro 的过程。 文章目录 一、eMMC二、SD 卡三、两个接口的区别一、eMMC RK3399 的 eMMC 接口如图: datasheet 介绍: 实际上,连接 eMMC 存储器用的是 SDHCI 接口。SDHCI(Secure Digital Host Controller Interface)…

【数据结构】最短路径——Floyd算法

一.问题描述 给定带权有向图G&#xff08;V&#xff0c;E&#xff09;&#xff0c;对任意顶点 V &#xff08;ij)&#xff0c;求顶点到顶点的最短路径。 转化为&#xff1a; 多源点最短路径求解问题 解决方案一&#xff1a; 每次以一个顶点为源点调用Dijksra算法。时间复杂…

香港虚拟信用卡如何办理,支持香港apple id

什么是虚拟信用卡&#xff1f; 虚拟信用卡&#xff0c;英文称之为Virtual Credit Card Numbers&#xff0c;就是指没有实体卡片&#xff0c;是基于银行卡上面的BIN码所生成的虚拟账号。通常用于进行网络交易&#xff0c;使用起来很方便&#xff0c;也很安全。 它与实体信用卡…

算法-01-递归

1-理解递归 斐波那契数列&#xff08;Fibonacci sequence&#xff09;&#xff0c;又称黄金分割数列 &#xff0c;以兔子繁殖为例子而引入&#xff0c;故又称“兔子数列”&#xff0c;其数值为&#xff1a;1、1、2、3、5、8、13、21、34……特点是 从第三个数开始&#xff0c;第…

HOST文件被挟持,无法上网,如何解决。

问题&#xff1a; 晚上开机&#xff0c;突然发现无法联网&#xff0c;提示网络异常 解决&#xff1a; 首先网络诊断&#xff0c;host文件被劫持&#xff0c;修复后&#xff0c;仍然不行。 然后测试手机热点&#xff0c;发现仍然无法联网 尝试用火绒修复&#xff0c;无果。 所有…

Linux Camera Driver(2):CIS设备注册(DTS)

一:MIPI接口 1、硬件接口 MIPI接口以rv1109和gc2053的硬件为例进行说明: 2、ISP驱动 注意配置事项: endpoint配置,必须指定data-lanes,否则无法识别为mipi类型 链接方式:sensor->csi_dphy->isp->ispp (1)sensor节点配置 根据原理图可知:mipicsi_clk0即引…

Linux系统安装Python3环境

1、默认情况下&#xff0c;Linux会自带安装Python&#xff0c;可以运行python --version命令查看&#xff0c;如图&#xff1a; 我们看到Linux中已经自带了Python2.7.5。再次运行python命令后就可以使用python命令窗口了&#xff08;CtrlD退出python命令窗口&#xff09;。 2…

STM32F407-14.3.11-01互补输出和死区插入

互补输出和死区插入 高级控制定时器&#xff08;TIM1 和 TIM8&#xff09;可以输出两路互补信号&#xff0c;并管理输出的关断与接通瞬间。 这段时间通常称为死区&#xff0c;用户必须根据与输出相连接的器件及其特性&#xff08;电平转换器的固有延迟、开关器件产生的延迟...&…

MySQL之时间戳(DateTime和TimeStamp)

MySQL之时间戳&#xff08;DateTime和TimeStamp&#xff09; 文章目录&#xff1a; MySQL之时间戳&#xff08;DateTime和TimeStamp&#xff09;一、DateTime类型二、TimeStamp类型三、DateTime和TimeStamp的区别 当插入数据时&#xff0c;需要自动记录一个时间时候&#xff0c…

llama.cpp部署(windows)

一、下载源码和模型 下载源码和模型 # 下载源码 git clone https://github.com/ggerganov/llama.cpp.git# 下载llama-7b模型 git clone https://www.modelscope.cn/skyline2006/llama-7b.git查看cmake版本&#xff1a; D:\pyworkspace\llama_cpp\llama.cpp\build>cmake --…

git 本地改动无法删除

1. 问题 记录下git遇到奇怪的问题&#xff0c;本地有些改动不知道什么原因无法删除 git stash&#xff0c; git reset --hard HEAD 等都无法生效&#xff0c;最终通过强制拉取线上解决 如下图&#xff1a; 2. 解决 git fetch --all git reset --hard origin/master执行这两…

LeedCode刷题---双指针问题

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 双指针简介 常见的双指针有两种形式&#xff0c;一种是对撞指针&#xff0c;一种是左右指针。 对撞指针:一般用于顺序结构中&…

马斯克极简5步工作法 —— 筑梦之路

马斯克的五步流程法则&#xff1a; 第一步&#xff1a;确定需求 第二步&#xff1a;极力删除零件或过程 第三步&#xff1a;简化和优化 第四步&#xff1a;加快周期时间 第五步&#xff1a;自动化特别注意&#xff1a;完成前三步之前&#xff0c;千万不要考虑加速和自动化&…

JVM类加载全过程

Java虚拟机类加载的全过程&#xff0c;即加载&#xff0c;验证&#xff0c;准备&#xff0c;解析&#xff0c;初始化 一、加载 加载 是 类加载过程中的一个阶段&#xff0c; 有以下三部分组成 1&#xff09;通过一个类的全限定名来获取定义此类的二进制流 2&#xff09;将这…

跨域问题的解决办法

1、产生跨域问题样式 前台写完&#xff0c;直接访问后台接口&#xff0c;会产生跨域的问题&#xff0c;需要配置文件去解决这个问题 从源http://localhost:8080访问http://localhost:8088/books的XMLHttpRequest已被CORS策略阻止:请求的资源上没有Access- control - allow - o…

C++学习之路(十八)C++ 用Qt5实现一个工具箱(点击按钮以新窗口打开功能面板)- 示例代码拆分讲解

上篇文章&#xff0c;我们用 Qt5 实现了在小工具箱中添加了《增加托盘图标并且增加显示和退出菜单》功能。今天我们把按钮打开功能的方式改一改&#xff0c;让点击按钮以新窗口打开功能面板。下面我们就来看看如何来规划开发这样的小功能并且添加到我们的工具箱中吧。 老规矩&…

个人博客搭建保姆级教程-HTML页面编写篇

选择模板 首先我们要选一个好的模板&#xff0c;然后对模板进行剪裁。我的模板是在站长之家进行下载的 素材下载-分享综合设计素材免费下载的平台-站长素材 我选的模板的具体地址是 个人博客资讯网页模板 这里需要我们学习一下在前边一篇文章里提到的HTML、JavaScript、CSS…