概念和用途
- 散列后的数据可以快速插入取用
- 在散列表上插入、删除和取用数据非常快,但是查找数据却效率低下,比如查找一组数据中的最大值和最小值
- ◆JavaScript散列表基于数组设计,理想情况散列函数会将每一个键值映射为唯的数组索引,数组长度有限制,更现实的策略是将键均匀分布。
关键定义
- 两个键值相同的情况,这种现象称为碰撞
- 数组长度应该是一个质数,所有策略都基于碰撞
- 开链法:两个键相同保存位置一样,开辟第二数组,也称第二个数组为链
- 线性探测法属于开放寻址散列,查找散列位置如果当前位置没有继续寻找下一个位置。
- 存储数据较大较合适。数组大小》=1.5数据,使用开链法,数组大小》=2数据,使用线性探测法。
代码实现
function hashTable() { // 1. 给质数长度的数组,为了防碰撞 this.table = new Array(159) // 2.1 获取hash this.simpleHash = simpleHash // 2.2 展示hash this.display = display // 2.3 增 this.put = put // 2.4 查 this.get = get // 3.1 解决碰撞1:betterHash this.betterHash = betterHash // 3.2 解决碰撞2:开链法——创造一个数组,存在了就push进去 this.buildChain = buildChain // 3.3 解决碰撞3:线性探测法——如果碰撞了,则一直往下找到没有碰撞的位置(如果找到最后都没有位置呢?插入失败?)}function buildChain () { for (let index = 0; index < this.table.length; index++) { this.table[index] = [] }}function simpleHash(ele) { var total = 0; for (let index = 0; index < ele.length; index++) { // string.charCodeAt(i) string.charAt(i) // 'abc'.charCodeAt(1) == 98 'abc'.charAt(1) == b total += ele.charCodeAt(index) } // 就这么记吧,我也不知道为啥,哎 // console.log('simpleHash res is :', total % 137) return total % 137}function betterHash(ele) { // 放大算法,在total上乘上个质数 让结果更均匀一些 const GG = 99 var total = 0; for (let index = 0; index < ele.length; index++) { total += total * GG + ele.charCodeAt(index) } console.log('simpleHash res is :', total % 137) return total % 137}function display() { for (let index = 0; index < this.table.length; index++) { if (this.table[index]) { console.log(`index: ${index}, value: ${this.table[index]}`) } // 开链法改造: // if (this.table[index][0]) { // console.log(`index: ${index}, value: ${this.table[index]}`) // } }}function put(ele) { var pos = this.simpleHash(ele) // this.table[pos] = ele // 线性探测法判断空位 if (!this.table[pos]) { this.table[pos] = ele } else { while(this.table[pos] != undefined) { pos++ } this.table[pos] = ele } // 开链法改造: // var index = 0 // if (!this.table[pos][index]) { // this.table[pos][index] = ele // } else { // while(this.table[pos][index] != undefined) { // index++ // } // this.table[pos][index] = ele // }}function get(ele) { // 第一次实现是下面这个东西,看起来很蠢 // return this.table[key] // 课程实现的是下面这东西,看起来很厉害的蠢 // return this.table[this.simpleHash(ele)] // 线性探测法,来获取原本的index和最终的index var hash = this.simpleHash(ele) // 从hash开始是因为碰撞是从 hash开始的 console.log('原始hash: ', hash) for (let index = hash; index < this.table.length; index++) { if (this.table[index] == ele) { return index } } return false}var hashT = new hashTable()// hashT.buildChain()hashT.put('china')hashT.put('japan')hashT.put('america')// 与china产生了碰撞,接下来改进hash算法hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')hashT.put('incha')console.log('length:', hashT.table.length, '------------------------')// 所以就溢出了呗,这个后面有用到这玩意再说吧,先了解着hashT.display()console.warn(hashT.get('incha'))