使用JavaScript实现一个简单的哈希映射功能

 更新时间:2024年02月28日 08:27:43   作者:JYeontu  
哈希表大家应该都经常用到吧,那么大家有没有想过哈希表是怎么实现的呢,本文我们就来从一道简单的题目来了解一下哈希表的简单原理和实现吧

说在前面

哈希表大家应该都经常用到吧,那么大家有没有想过哈希表是怎么实现的呢?今天让我们一起从一道简单的题目来初步了解一个哈希表的简单原理。

目的

不使用任何内建的哈希表库设计一个哈希映射(HashMap)。

实现 MyHashMap 类:

  • MyHashMap() 用空映射初始化对象
  • void put(int key, int value) 向 HashMap 插入一个键值对 (key, value) 。如果 key 已经存在于映射中,则更新其对应的值 value 。
  • int get(int key) 返回特定的 key 所映射的 value ;如果映射中不包含 key 的映射,返回 -1 。
  • void remove(key) 如果映射中存在 key 的映射,则移除 key 和它所对应的 value 。

示例:

//输入:
["MyHashMap", "put", "put", "get", "get", "put", "get", "remove", "get"]
[[], [1, 1], [2, 2], [1], [3], [2, 1], [2], [2], [2]]
//输出:
[null, null, null, 1, -1, null, 1, null, -1]

//解释:
MyHashMap myHashMap = new MyHashMap();
myHashMap.put(1, 1); // myHashMap 现在为 [[1,1]]
myHashMap.put(2, 2); // myHashMap 现在为 [[1,1], [2,2]]
myHashMap.get(1);    // 返回 1 ,myHashMap 现在为 [[1,1], [2,2]]
myHashMap.get(3);    // 返回 -1(未找到),myHashMap 现在为 [[1,1], [2,2]]
myHashMap.put(2, 1); // myHashMap 现在为 [[1,1], [2,1]](更新已有的值)
myHashMap.get(2);    // 返回 1 ,myHashMap 现在为 [[1,1], [2,1]]
myHashMap.remove(2); // 删除键为 2 的数据,myHashMap 现在为 [[1,1]]
myHashMap.get(2);    // 返回 -1(未找到),myHashMap 现在为 [[1,1]]

提示:

0 <= key, value <= 10^6

最多调用 10^4 次 putget 和 remove 方法

实现思路

什么是哈希表

哈希表是一种通过将键映射到特定位置来实现快速查找的数据结构。它的设计原理主要包括以下几个关键概念:

  • 哈希函数:哈希表的核心在于哈希函数,它能够将任意大小的输入数据转换成固定大小的输出值(通常是一个整数),并且应该尽可能地降低冲突的概率。一个好的哈希函数应该具有均匀分布性,即对于输入的改变,哈希值的变化应该是不可预测的。这样可以尽可能地避免键的碰撞,提高哈希表的性能。
  • 数组存储:哈希表内部通常采用数组来存储数据。哈希函数会将键映射到数组的特定位置,这个位置通常被称为槽(slot)。在大多数情况下,哈希表的槽数量会远远大于实际存储的元素数量,以减少碰撞的概率。
  • 解决碰撞:由于哈希函数的输出空间通常要小于输入空间,所以不同的键可能会映射到同一个槽中,造成碰撞(collision)。解决碰撞的常见方法包括链地址法(Chaining)和开放寻址法(Open Addressing)等。链地址法将同一个槽中的元素组织成链表、树或者其他数据结构;开放寻址法则在发生碰撞时寻找下一个可用的槽位。
  • 性能分析:对于哈希表的性能分析包括哈希函数的设计、负载因子的管理、碰撞处理的效率等方面。良好的哈希函数和合理的负载因子管理能够有效地提高哈希表的性能。

总的来说,哈希表通过哈希函数将键映射到数组中的特定位置,从而实现了快速的查找、插入和删除操作。良好的哈希表设计能够在平均情况下获得较高的性能,成为计算机科学中重要的数据结构之一。

分配数组空间

分配指定长度的数组作为存储空间。

var MyHashMap = function () {
  this.BASE = 666;
  this.data = new Array(this.BASE)
    .fill(0)
    .map(() => new Array(2).fill(0).map(() => new Array()));
};

获取key的哈希值

这道题目限制了key为数字,所以我们可以简单的通过求模来作为每个key的哈希值。

const index = key % this.BASE;

put方法

/**
 * @param {number} key
 * @param {number} value
 * @return {void}
 */
MyHashMap.prototype.put = function (key, value) {
  const index = key % this.BASE;//获取存储哈希
  let keyInd = this.data[index][0].indexOf(key);//获取该key所在位置
  if (keyInd == -1) {//不存在的话直接新增
    this.data[index][0].push(key);
    this.data[index][1].push(value);
  } else this.data[index][1][keyInd] = value;//存在则更新值
};

get方法

/**
 * @param {number} key
 * @return {number}
 */
MyHashMap.prototype.get = function (key) {
  const index = key % this.BASE;//获取存储哈希
  let keyInd = this.data[index][0].indexOf(key);//获取该key所在位置
  if (keyInd == -1) {//不存在的话直接返回-1
    return -1;
  }
  return this.data[index][1][keyInd];//存在则返回存储的值
};

remove方法

/**
 * @param {number} key
 * @return {void}
 */
MyHashMap.prototype.remove = function (key) {
  const index = key % this.BASE;//获取存储哈希
  let keyInd = this.data[index][0].indexOf(key);//获取该key所在位置
  if (keyInd == -1) {//不存在的话直接返回
    return;
  }
  //存在的话则将key和值都删除
  this.data[index][0].splice(keyInd, 1);
  this.data[index][1].splice(keyInd, 1);
};

完整代码

var MyHashMap = function () {
  this.BASE = 666;
  this.data = new Array(this.BASE)
    .fill(0)
    .map(() => new Array(2).fill(0).map(() => new Array()));
};

/**
 * @param {number} key
 * @param {number} value
 * @return {void}
 */
MyHashMap.prototype.put = function (key, value) {
  const index = key % this.BASE;
  let keyInd = this.data[index][0].indexOf(key);
  if (keyInd == -1) {
    this.data[index][0].push(key);
    this.data[index][1].push(value);
  } else this.data[index][1][keyInd] = value;
};

/**
 * @param {number} key
 * @return {number}
 */
MyHashMap.prototype.get = function (key) {
  const index = key % this.BASE;
  let keyInd = this.data[index][0].indexOf(key);
  if (keyInd == -1) {
    return -1;
  }
  return this.data[index][1][keyInd];
};

/**
 * @param {number} key
 * @return {void}
 */
MyHashMap.prototype.remove = function (key) {
  const index = key % this.BASE;
  let keyInd = this.data[index][0].indexOf(key);
  if (keyInd == -1) {
    return;
  }
  this.data[index][0].splice(keyInd, 1);
  this.data[index][1].splice(keyInd, 1);
}

到此这篇关于使用JavaScript实现一个简单的哈希映射功能的文章就介绍到这了,更多相关JavaScript哈希映射内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JS设计模式之状态模式的用法使用方法

    JS设计模式之状态模式的用法使用方法

    JavaScript状态模式是一种行为型设计模式,核心是对象在其内部状态改变时改变其行为,状态模式将对象的行为封装到不同的状态类中,使得对象在不同状态下可以选择不同的行为,本文给大家详细的介绍一下状态设计模式在Js中的使用,需要的朋友可以参考下
    2023-08-08
  • 微信小程序从服务器中获取数据的示例代码

    微信小程序从服务器中获取数据的示例代码

    要从服务器中获取数据,可以使用微信小程序提供的wx.request()方法,下面通过示例代码介绍微信小程序怎么从服务器中获取数据,感兴趣的朋友一起看看吧
    2024-03-03
  • JavaScript实现文件下载的超简单两种方式分享

    JavaScript实现文件下载的超简单两种方式分享

    这篇文章主要为大家详细介绍了JavaScript实现文件下载的超简单两种方式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12
  • JavaScript实现文本相似度对比

    JavaScript实现文本相似度对比

    这篇文章主要介绍了JavaScript实现文本相似度对比,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-06-06
  • js中find、findIndex、indexOf的用法和区别

    js中find、findIndex、indexOf的用法和区别

    本文主要介绍了js中find、findIndex、indexOf的用法和区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • 小程序组件之自定义顶部导航实例

    小程序组件之自定义顶部导航实例

    这篇文章主要给大家介绍了关于小程序组件之自定义顶部导航的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用小程序具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • JavaScript不使用prototype和new实现继承机制

    JavaScript不使用prototype和new实现继承机制

    这篇文章主要介绍了JavaScript不使用prototype和new实现继承机制的相关资料,需要的朋友可以参考下
    2014-12-12
  • IE6-IE9使用JSON、table.innerHTML所引发的问题

    IE6-IE9使用JSON、table.innerHTML所引发的问题

    这篇文章主要介绍了IE6-IE9使用JSON、table.innerHTML所引发的问题 ,需要的朋友可以参考下
    2015-12-12
  • JavaScript实现16进制颜色值转RGB的方法

    JavaScript实现16进制颜色值转RGB的方法

    这篇文章主要介绍了JavaScript实现16进制颜色值转RGB的方法,是javascript比较典型的数值转换应用技巧,非常具有实用价值,需要的朋友可以参考下
    2015-02-02
  • vue渲染大量数据时卡顿卡死解决方法

    vue渲染大量数据时卡顿卡死解决方法

    这篇文章主要介绍了vue渲染大量数据时发生卡顿卡死问题时的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08

最新评论