JavaScript 数据结构之散列表的创建(2)

 更新时间:2022年04月22日 17:12:54   作者:杨成功   
这篇文章主要介绍了 JavaScript 数据结构之散列表的创建,主要看如何处理散列值冲突的问题,并实现更完美的散列表。下文详细介绍需要的小伙伴可以参考一下

前言:

上一篇我们介绍了什么是散列表,并且用通俗的语言解析了散列表的存储结构,最后动手实现了一个散列表,相信大家对散列表已经不陌生了。

如果还不清楚散列表,请先阅读上一篇文章:JavaScript 数据结构之散列表的创建(1)

上篇末尾我们遗留了一个问题,就是将字符串转化为散列值后可能出现重复。当以散列值(hash 值)为 key 存储数据时,就会有覆盖已有数据的风险。本篇我们看如何处理散列值冲突的问题,并实现更完美的散列表。

一、处理散列值冲突

有时候一些键会有相同的散列值。比如 aab 和 baa,从字符串的角度来说它们是不同的值,但是按照我们的散列函数逻辑,将每个字母的 Unicode 码累加得出的散列值,一定是一样的。

我们知道在 JavaScript 对象当中,如果赋值时指定的 key 已存在,那么就会覆盖原有的值,

比如这个例子:

var json = { 18: '雷欧' }
json[18] = '欧布'
console.log(json) // { 18: '欧布' }

为了避免上述代码中出现的风险,我们需要想办法处理,如何使 key != key,则 hash != hash

目前可靠的方法有两个,分别是:分离链接 和 线性探查

1.分离链接

分离链接法是指在散列表存储数据时,value 部分用 链表 来代替之前的 键值对。键值对只能存储一个,而链表可以存储多个键值对。如果遇到相同的散列值,则在已有的链表中添加一个键值对即可。

我们需要重写三个方法:put、get 和 remove。我们看如何实现:

class HashTableSeparateChaining {
  constructor() {
    this.table = {}
  }
}

2.put 方法

首先还是基本的类结构,然后看 put 方法:

put(key, value) {
  if(key !== null && value !== null) {
    let pos = this.hashCode(key)
    if(!this.table[pos]) {
      this.table[pos] = new LinkedList()
    }
    this.table[pos].push(new ValuePair(key, value))
    return true;
  }
  return false;
}

LinkedList 类是标准的链表类,在链表篇讲过如何实现,这里直接使用

对比上篇的散列表 put 方法,你会发现差别不大,变化的部分如下:

// 变化前
this.table[pos] = new ValuePair(key, value)
// 变化后
if(!this.table[pos]) {
  this.table[pos] = new LinkedList()
}
this.table[pos].push(new ValuePair(key, value))

优化后的逻辑是,在存储数据时,将键值对存在一个链表里。如果有相同的 hash 值,则向已有的链表中添加一个键值对,这样就避免了覆盖。

不过这种方式也有弊端,每添加一个键值对就要创建一个链表,会增加额外的内存空间。

3.get 方法

get 方法:

get(key) { 
  let linkedList = this.table[this.hashCode(key)]
  if(linkedList && !linkedList.isEmpty()) {
    let current = linkedList.getItemAt(0);
    while(current) {
      if(current.value.key == key) {
        return current.value.value
      }
      current = current.next
    }
  }
  return undefined; 
}

新的 get 方法明显比之前的复杂了许多。主要逻辑是根据 key 找到一个链表,然后再遍历链表找到与参数 key 相匹配的键值对,最后返回找到的值。

while 循环中使用 return 可以直接中止当前函数

到此这篇关于 JavaScript 数据结构之散列表的创建的文章就介绍到这了,更多相关 JavaScript 散列表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • ECharts坐标轴刻度数值处理方法例子

    ECharts坐标轴刻度数值处理方法例子

    这篇文章主要给大家介绍了关于ECharts坐标轴刻度数值处理的相关资料,文章介绍了一个用于图表Y轴数值简写的函数,它可以将大数值转换为K、M、B等简写形式,从而使图表更加美观和易读,需要的朋友可以参考下
    2024-11-11
  • typescript+react实现移动端和PC端简单拖拽效果

    typescript+react实现移动端和PC端简单拖拽效果

    这篇文章主要为大家详细介绍了typescript+react实现移动端和PC端简单拖拽效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • js中判断两个数组对象是否完全相等

    js中判断两个数组对象是否完全相等

    这篇文章主要介绍了js中判断两个数组对象是否完全相等方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • 7个令人惊讶的JavaScript特性详解

    7个令人惊讶的JavaScript特性详解

    在学习ES6的过程中我碰到了几个特性,它们让我惊讶,其中大部分是关于 ES6 的特性但也有一部分是 ES3 特性,这些特性我以前从未用过,而现在我将开始使用它们,感兴趣的小伙伴可以跟着小编一起来学习
    2023-05-05
  • js千分位实现方法大汇总

    js千分位实现方法大汇总

    这篇文章主要介绍了js千分位实现方法大汇总,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • JS简单实现仿百度控制台输出信息效果

    JS简单实现仿百度控制台输出信息效果

    这篇文章主要介绍了JS简单实现仿百度控制台输出信息效果,涉及javascript中console.log函数的简单使用技巧,需要的朋友可以参考下
    2016-09-09
  • JSON与JavaScript对象关系及语法规则详解

    JSON与JavaScript对象关系及语法规则详解

    这篇文章主要为大家介绍了JSON与JavaScript对象关系及语法规则详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • MVVM框架下实现分页功能示例

    MVVM框架下实现分页功能示例

    分页这种组件,几乎每一种框架都有这样的组件,这篇文章主要介绍了MVVM框架下实现分页功能示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • js实现input框文字动态变换显示效果

    js实现input框文字动态变换显示效果

    这篇文章主要介绍了js实现input框文字动态变换显示效果,涉及javascript随机字符串与中文的动态切换显示效果,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-08-08
  • javascript使用Blob对象实现的下载文件操作示例

    javascript使用Blob对象实现的下载文件操作示例

    这篇文章主要介绍了javascript使用Blob对象实现的下载文件操作,结合实例形式分析了javascript使用Blob对象下载文件相关原理、操作技巧与注意事项,需要的朋友可以参考下
    2020-04-04

最新评论