1.简介

哈希表(hash table)又被称为散列表,可能是翻译的问题好多书上一会儿称散列一会儿称哈希,更有甚者煞有介事的对此进行区分。经过简单的搜索(wiki链接)发现这两个词是一回事。由此可见学好英语是多么重要。(我是一名渴望学好英语的英文渣。。)

1.1定义

这里引用一下维基百科的定义:

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

这段话里加粗的地方暂时存疑,因为和下一句话说法有冲突,感觉改为根据哈希函数与键计算出来的值,即哈希值访问内存存储位置的数据结构会好点(当然也有可能是我阅读理解不好,哈哈)

1.2一些点

哈希表是

  • 一种动态(指数据存入后,还会进行增删查改等工作)集合结构
  • 至少需要支持insert,search,delete等操作
  • 普通数组的推广概念

    • 数组是直接寻址
    • 当实际存储的key数量小于key的总数量,使用哈希表是直接数组寻址的有效替代
  • 不是直接把key作为数组下标,而是根据哈希函数与key计算出相应的下标

2直接寻址表(direct-address table)

2.1废话

资料找多了会发现一个很严重的问题,它们之间可能会有冲突,从简介中介绍的名字问题就可以看出。同样,有些书把直接寻址表也视作一种哈希表,不过哈希表既然是数组的一种推广,那也就不要在这些细枝末节上计较了。

2.2介绍

当关键词的数量比较小时,这种方法是一种简单有效的方法,在我的文章《如何随机&&去重返回新数组》中3.1节给出的方法就用到了直接寻址处理问题,代码中数组indexArr就是。这是一种空间换时间的做法,定义一个大于等于key数量的数组,value部分全部初始化为null,然后进行数据的存取。这也是我们经常使用的。

3哈希表(hash table)

直接寻址的缺点在于如果数据量很大,占用空间就很大,因为首先你得初始化一个巨大的数组,无论数据是否存入。如果用一句话总结哈希表就是:hash浓缩为一句话:将元素通过一个函数转换为整数,使得该整数可以尽量唯一的表达这个元素

3.1js中数组和对象与哈希表的关系

但是在js中其实这个问题有待于商榷,因为js的数组还有对象都可以存任意键值而且无需提前定义长度,还可以随意增删。所以有的文章就指出其实js的数组和对象就的底层实现就是哈希表(文章地址),虽然文章中只是提到对象,但是基于js存在key-value形式的数组,我猜原理应该很是类似。

3.2基础的哈希函数

设哈希函数为H,数据的键设为key,转换后的值为整数H(key)。常见的有平方取中发,除留余数法,线性变化法(H(key)=a*key+b)。这里着重介绍除留余数法。

3.2.1除留余数法

公式:
$$ H(key)=key\%mod $$

把key除以一个数mod得到的余数作为hash值的方法,通过这个哈希函数可以把很大的数转换为不超过mod的整数,这表示数组的长度必须不小于mod(js中无所谓),当mod是一个素数时H(key)能尽可能的覆盖[0,mod)范围内的每一个数。

3.3冲突

看3.2.1的公式就可以知道,必然会出现两个不同的key1,key2他们的hash的值H(key1)=H(key2)。如果直接把hash值作为数组下表标则会出现覆盖的情况,我们称之为冲突,由此看出hash函数不是单射,这样也就表明hash值是不可逆的。

3.3.1常见的解决冲突的方法

  1. 线性探查法
  2. 平方探查法
  3. 链地址法

1,2都要重新计算hash值,3不需要,而且3是C语言里常见的解决方法,思想是把所有H(key)相同的key连成一条单链表(当然用一个数组也是可以的),然后查找时遍历单链表寻找数据。这些都是底层,大部分语言都封装有库。

3.4字符串hash初步

字符串hash是指将一个字符串S映射为一个整数,使得该整数可以尽可能唯一地代表字符串S。为什么要这么做呢,因为好多语言的数组的下标只能接受整数,例如C语言这种静态的语言和js这种动态语言数据存储上差异很大。js中使用对象存储key-value形式的数据增删查改都非常方便,但是在C语言中需要很多数据结构配合的使用才能实现。

  function hashFunc(s='hello word'){let id=0,len,arr=[];len=s.length;arr=s.split("");for(let i=0;i<len;i++){id += arr[i].charCodeAt();//str.charCodeAt(index)用于获取字符的ascii码}return id%57;//找一个素数用来限制数组大小}

js实现这个函数还是很方便的,就是字符ascii码相加即可。当然还可以使用更复杂的方式来避免冲突。

3.5js实现哈希表

我们将要实现hashTable这个类分别实现插入、查找、删除、打印等方法。

    class HashTable {constructor() {this.table = {'3212':{'ddd':'ddd','ee':'2312'}};//测试递归是否正常}_hashFunc(key) {let id = 0, len, arr = [];len = key.length;arr = key.split("");for (let i = 0; i < len; i++) {id += arr[i].charCodeAt();//str.charCodeAt(index)用于获取字符的ascii码}return id%57;//找一个素数用来限制数组大小}insert(key,value){if(typeof key !='object'){//可以只接受一个对象let id = this._hashFunc(key);if(!this.table[id]){this.table[id]={};}if(!this.table[id][key]){this.table[id][key]=value;}}else{for(let i in key){this.insert(i,key[i])}}}search(key){let id = this._hashFunc(key);if(!this.table[id] || !this.table[id][key]) return null;return this.table[id][key];}delete(key){let id = this._hashFunc(key);if(this.table[id])if(this.table[id][key])return delete this.table[id][key]}print(table=this.table){//递归输出hashtable的值if(typeof table=='object'){for(let key in table){this.print(table[key])if(typeof table[key]!='object')console.log(key,'+',table[key])}}}}let hash = new HashTable()hash.insert({'abc':'ddd@qq.com','bac':'33@qq.com','ddic':'2343@gmail.com'});hash.print();console.warn('delete abc')hash.delete('abc');hash.print();console.log(hash.search('bac'))

这个代码里用了对象嵌套对象的形式实现了链地址法处理冲突在C语言中会选择数组+链表的形式实现,当后面写到链表的时候会重新改一下。其实就像上文中所述,js中的对象可能就是封装一个哈希表,而且key值是唯一的,连哈希函数貌似都可以省了了。

参考书目

《算法笔记》
《算法导论》
《学习JavaScript数据结构与算法》
《ECMAScript 6 入门》

js算法入门(2)--哈希表相关推荐

  1. ⭐算法入门⭐《哈希表》中等05 —— LeetCode 215. 数组中的第K个最大元素

    文章目录 一.题目 1.题目描述 2.基础框架 3.原题链接 二.解题报告 1.思路分析 2.时间复杂度 3.代码详解 三.本题小知识 四.加群须知 一.题目 1.题目描述   给定整数数组nums和 ...

  2. 数据结构与算法五:哈希表-哈希函数设计原则-哈希冲突解决方案

    一.哈希表的定义: 二.哈希表举例: 哈希函数就是映射关系 三.哈希表应用举例: Leetcode上第387题: 思路:通过s.charAt(i)-'a'将字符串中的字符映射成hash表,出现一次,在 ...

  3. 【JS数据结构与算法】认识哈希表

    目录 一.什么是哈希表? 二.哈希表的优势. 三.哈希表与数组相比较. 四.数据的存储. 方法一:ASCII编码之和 方法二:幂的连乘 五.方法二改进--哈希化 六.解决冲突 一:链地址法(拉链法). ...

  4. python【数据结构与算法】深入浅出哈希表

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

  5. 数据结构与算法笔记:哈希表——力扣389

    原题: 给定两个字符串 s 和 t ,它们只包含小写字母.字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母.请找出在 t 中被添加的字母. 思路: 首先咱们抛开编程知识,就当它是咱们日常 ...

  6. 一文带你快速入门【哈希表】

    最近开始学习哈希表,为此特写一遍文章介绍一下哈希表,带大家快速入门哈希表

  7. C++(数据结构与算法):30---散列(哈希)表的介绍(散列函数、散列冲突、散列溢出)

    一.散列(哈希)介绍 散列使用一个散列函数(也称为哈希函数)把字典的数对映射到一个散列表(也称为哈希表)的具体位置 散列的存储与查找: 查找:如果数对p的关键字是k,散列函数为f,那么在理想的情况下, ...

  8. 数据结构与算法——深入理解哈希表

    文章目录 哈希表 优点与缺点 哈希化 冲突 基于线性探测的开放地址法 插入 查找 删除 性能问题 基于二次探测的开放地址法 基于再哈希法的开放地址法 链地址法 哈希表实现方法的选择 参考 哈希表 哈希 ...

  9. 浅谈算法和数据结构: 哈希表

    作者: yangecnu(yangecnu's Blog on 博客园) 出处:http://www.cnblogs.com/yangecnu/  http://www.cnblogs.com/yan ...

最新文章

  1. 人工智能入门(二):语音识别基本模型
  2. python 报错 xxx is not callable 原因及解决办法
  3. 实验3 分支语句和循环语句(1)
  4. java 悬浮提示框_表格(悬浮框提示)
  5. Solr6.1 smartCN配置
  6. 苹果A13和A11性能差距有多大?
  7. 自定义view跟手移动android,Android自定义view圆并随手指移动
  8. testbench文件显示波形_如何编写testbench的总结(非常实用的总结)
  9. unity 自定义渲染管线
  10. 网络安全-技术与实践 书本习题练习
  11. ​交大最新研究:长江学者和杰青平均在47岁前达到科研产出高峰
  12. CentOS 7 时区设置
  13. Go语言的流程结构简单介绍
  14. 学生博客,教师博客地址,有用博客地址
  15. 市盈率指标详解及相关文献概述
  16. Javascript错误处理——try...catch
  17. 洗车行业可以使用会员管理系统吗?
  18. 历年国二c语言真题百度网盘 下载,历年国家计算机二级C语言上机国二真题整理100套...
  19. 关于CAD中不显示黑体或是黑体字显示为问号的原因
  20. Windows 电脑屏幕卡住问题解决方案

热门文章

  1. eeglab中文教程系列(15)-绘制独立成分ERP贡献
  2. 英特尔芯片专利官司败诉,判罚140亿,半个季度白干了...
  3. OpenAI的GPT-3花费了1200万美元,现在放出商用API,人人皆可拿来自动生成文本、编写代码...
  4. Lyft开源L5自动驾驶数据集:55000个人工标注的3D注释框架,还有高清空间语义地图...
  5. 让你热血沸腾的电竞直播,有一群深藏不露的技术极客
  6. 『中级篇』docker之CI/CD持续集成-项目生成镜像(76)
  7. Spring Data JPA 复杂/多条件组合分页查询
  8. 【OpenStack】OpenStack系列6之Sheepdog环境搭建
  9. eclipse提交项目到github
  10. Web APi之控制器创建过程及原理解析(八)