问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

哈希表详细介绍,包括相关性质

发布网友 发布时间:2022-05-11 16:44

我来回答

2个回答

懂视网 时间:2022-05-14 17:32

本篇文章给大家带来的内容是关于JavaScript中散列表(哈希表)的详细介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

散列表

散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表。

2472848212-5c2afb47f10ad_articlex.png

我们从上图开始分析

  • 有一个集合U,里面分别是1000,10,152,9733,1555,997,1168

  • 右侧是一个10个插槽的列表(散列表),我们需要把集合U中的整数存放到这个列表中

  • 怎么存放,分别存在哪个槽里?这个问题就是需要通过一个散列函数来解决了。我的存放方式是取10的余数,我们对应这图来看

  • 1000%10=0,10%10=0 那么1000和10这两个整数就会被存储到编号为0的这个槽中

  • 152%10=2那么就存放到2的槽中

  • 9733%10=3 存放在编号为3的槽中

  • 通过上面简单的例子,应该会有一下几点一个大致的理解

  • 集合U,就是可能会出现在散列表中的键

  • 散列函数,就是你自己设计的一种如何将集合U中的键值通过某种计算存放到散列表中,如例子中的取余数

  • 散列表,存放着通过计算后的键

  • 那么我们在接着看一般我们会怎么去取值呢?

    比如我们存储一个key为1000,value为'张三' ---> {key:1000,value:'张三'}
    从我们上述的解释,它是不是应该存放在1000%10的这个插槽里。
    当我们通过key想要找到value张三,是不是到key%10这个插槽里找就可以了呢?到了这里你可以停下来思考一下。

    散列的一些术语(可以简单的看一下)

  • 散列表中所有可能出现的键称作全集U

  • 用M表示槽的数量

  • 给定一个键,由散列函数计算它应该出现在哪个槽中,上面例子的散列函数h=k%M,散列函数h就是键k到槽的一个映射。

  • 1000和10都被存到了编号0的这个槽中,这种情况称之为碰撞。

  • 看到这里不知道你是否大致理解了散列函数是什么了没。通过例子,再通过你的思考,你可以回头在读一遍文章头部关于散列表的定义。如果你能读懂了,那么我估计你应该是懂了。

    常用的散列函数

    处理整数 h=>k%M (也就是我们上面所举的例子)

    处理字符串:

     function h_str(str,M){
     return [...str].reduce((hash,c)=>{
      hash = (31*hash + c.charCodeAt(0)) % M
     },0)
     }

    hash算法不是这里的重点,我也没有很深入的去研究,这里主要还是去理解散列表是个怎样的数据结构,它有哪些优点,它具体做了怎样一件事。
    而hash函数它只是通过某种算法把key映射到列表中。

    构建散列表

    通过上面的解释,我们这里做一个简单的散列表

    散列表的组成

  • M个槽

  • 有个hash函数

  • 有一个add方法去把键值添加到散列表中

  • 有一个delete方法去做删除

  • 有一个search方法,根据key去找到对应的值

  • 初始化

    - 初始化散列表有多少个槽
    - 用一个数组来创建M个槽

     class HashTable {
     constructor(num=1000){
      this.M = num;
      this.slots = new Array(num);
     }
     }

    散列函数

    处理字符串的散列函数,这里使用字符串是因为,数值也可以传换成字符串比较通用一些

    先将传递过来的key值转为字符串,为了能够严谨一些

    将字符串转换为数组, 例如'abc' => [...'abc'] => ['a','b','c']

    分别对每个字符的charCodeAt进行计算,取M余数是为了刚好对应插槽的数量,你总共就10个槽,你的数值%10 肯定会落到 0-9的槽里

     h(str){
     str = str + '';
     return [...str].reduce((hash,c)=>{
      hash = (331 * hash + c.charCodeAt()) % this.M;
      return hash;
     },0)
     }

    添加

    调用hash函数得到对应的存储地址(就是我们之间类比的槽)

    因为一个槽中可能会存多个值,所以需要用一个二维数组去表示,比如我们计算得来的槽的编号是0,也就是slot[0],那么我们应该往slot[0] [0]里存,后面进来的同样是编号为0的槽的话就接着往slot[0] [1]里存

     add(key,value) {
     const h = this.h(key);
     // 判断这个槽是否是一个二维数组, 不是则创建二维数组
     if(!this.slots[h]){
      this.slots[h] = [];
     }
     // 将值添加到对应的槽中
     this.slots[h].push(value);
     }

    删除

    通过hash算法,找到所在的槽

    通过过滤来删除

     delete(key){
     const h = this.h(key);
     this.slots[h] = this.slots[h].filter(item=>item.key!==key);
     }

    查找

    通过hash算法找到对应的槽

    用find函数去找同一个key的值

    返回对应的值

     search(key){
     const h = this.h(key);
     const list = this.slots[h];
     const data = list.find(x=> x.key === key);
     return data ? data.value : null; 
     }

    总结

    讲到这里,散列表的数据结构已经讲完了,其实我们每学一种数据结构或算法的时候,不是去照搬实现的代码,我们要学到的是思想,比如说散列表它究竟做了什么,它是一种存储方式,可以快速的通过键去查找到对应的值。那么我们会思考,如果我们设计的槽少了,在同一个槽里存放了大量的数据,那么这个散列表它的搜索速度肯定是会大打折扣的,这种情况又应该用什么方式去解决,又或者是否用其他的数据结构的代替它。

    补充一个小知识点

    v8引擎中的数组 arr = [1,2,3,4,5] 或 new Array(100) 我们都知道它是开辟了一块连续的空间去存储,而arr = [] , arr[100000] = 10 这样的操作它是使用的散列,因为这种操作如果连续开辟100万个空间去存储一个值,那么显然是在浪费空间。

    热心网友 时间:2022-05-14 14:40

    散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

    给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数
    声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
    我要问一下掇刀医保局恢复正常上班吗? 医保卡是东宝区的怎么才能转到掇刀区 东宝人社局 医保局 空调扇和风扇有什么区别 ...上了技校,现在上了电大的大专,档案在自己手里怎么办? 高职扩招的档案从哪里来 专科没有毕业档案怎么办 技校没上完考上专科,档案怎么转 凉薯和红薯有什么区别 凉薯和山药一样吗 我是一名教师 评职称发表论文 不知道网上哪些机构好点 具体? 哈希函数是唯一的吗?哈希值的问题 百度百科版本哈希值是什么? vim如何显示命令模式已经执行过的命令?如下图! 你最爱的一个 Vim 命令是什么? 查询vi vim命令存放的绝对路径 vim 怎么查看 tags列表 家常菜红烧牛肉怎么做? 怎样把我的世界里的十字变成圆 我的世界手机版怎么调箭头十字形 我的世界手机版pe怎么弄光标 我的世界手机版1.30怎么去除屏幕中心的十字光标? 微信加人提示操作频繁,请稍后重试 电脑主机蓝色灯不亮这是为什么? 碳氢清洗剂清洗剂 三氯乙烯与碳氢清洗剂的区别? ps中怎么把一张图片做四向延续 笔记本设置屏幕休眠时间不灭 三星笔记本屏幕怎么弄永远不灭 笔记本屏幕不关闭怎么设置? 中国最新人口普查 哈希函数有三个重要的性质 简述闭散列表解决冲突的基本思想 我家孩子在周浦二小上学,上了四年级后遇到这部编版教材,语文成绩一下掉下来了,想补一下语文,求推荐? 劳动仲裁能打赢吗? 拖欠工资劳动仲裁能赢吗 劳动仲裁没证据能赢吗 劳动仲裁赢得胜算大吗 没签劳动合同,如何赢得劳动仲裁? 劳动仲裁能赢吗 劳动仲裁裁决我赢了,单位不服,提出上诉,单位如有各种理由我能赢吗? 我已申请劳动仲裁,但我没有证据,我能赢吗? 关于劳动仲裁,根据我现在掌握的证据胜算大吗?如何应对才能胜利 拖欠工资去劳动仲裁能赢吗? 劳动仲裁一定会赢吗? 跟国企劳动仲裁能赢吗 民用建筑设计要求主要有哪些 建筑设计专业需要哪些方面的知识? 文天祥的事迹缩写20字 格力电器龙虎榜今日数据 帝科股份龙虎榜今日数据