哈希表(Hash Table)结构
核心特性
基于哈希函数实现键值映射,查询 / 增删 O (1)(理想情况)
核心概念:哈希函数(将键映射到数组索引)、冲突解决(拉链法 / 开放地址法)
前端关联:Object、Map 的底层实现本质是哈希表(Object 用拉链法解决冲突,Map 用平衡二叉搜索树优化有序性)
代码实现(拉链法解决冲突)
js
class HashTable {
constructor(capacity = 16) {
this.capacity = capacity; // 数组容量(2的幂次,便于哈希计算)
this.buckets = new Array(capacity).fill(null).map(() => []); // 每个桶是一个链表(存储冲突的键值对)
this.size = 0;
}
// 哈希函数(简单版:将键转为字符串,计算ASCII码之和,取模容量)
_hash(key) {
const strKey = String(key);
let hash = 0;
for (let i = 0; i < strKey.length; i++) {
hash += strKey.charCodeAt(i);
}
return hash % this.capacity;
}
// 新增/修改
set(key, value) {
const index = this._hash(key);
const bucket = this.buckets[index];
// 查找是否已存在该键,存在则更新值
for (let i = 0; i < bucket.length; i++) {
const [k, v] = bucket[i];
if (k === key) {
bucket[i] = [key, value];
return;
}
}
// 不存在则添加到桶中
bucket.push([key, value]);
this.size++;
// 扩容(负载因子>0.7时,避免冲突过多)
if (this.size / this.capacity > 0.7) {
this._resize();
}
}
// 查找
get(key) {
const index = this._hash(key);
const bucket = this.buckets[index];
for (const [k, v] of bucket) {
if (k === key) return v;
}
return undefined; // 未找到
}
// 删除
delete(key) {
const index = this._hash(key);
const bucket = this.buckets[index];
for (let i = 0; i < bucket.length; i++) {
const [k] = bucket[i];
if (k === key) {
bucket.splice(i, 1);
this.size--;
return true;
}
}
return false; // 未找到
}
// 扩容(容量翻倍,重新计算所有键的哈希值)
_resize() {
const oldBuckets = this.buckets;
this.capacity *= 2;
this.buckets = new Array(this.capacity).fill(null).map(() => []);
this.size = 0;
// 重新插入所有键值对
for (const bucket of oldBuckets) {
for (const [key, value] of bucket) {
this.set(key, value);
}
}
}
}适用场景
常见数据查询:如缓存池(存储接口返回数据,键为请求 URL,值为响应数据)
字典映射:如中英文翻译(键为英文单词,值为中文释义)
计数统计:如统计字符串中字符出现次数(键为字符,值为次数)
注意
哈希函数的选择影响冲突率(好的哈希函数能均匀分布键)
负载因子(size/capacity)过大时需扩容(否则冲突增多,查询效率下降)
