js实现封装哈希表
1.哈希表的原理
** 1.哈希表需要用数组来储存数据*
** 2.每个数组的下表是通过哈希函数来生成的*
** 3.哈希表的空间必须比要容纳的内容元素多*
** 4.一般遇到冲突使用链地址法来解决*
2.注意事项
2.1 实现高效的哈希函数
哈希函数是整个哈希表的一个灵魂,通过哈希函数,可以把字段转化成hascode作为数组下标,实现哈希函数,可以使用霍纳法则,来简化多项式相乘的次数。
** 为什么要使用霍纳法则?*
** 对于单词转换成数字的时候,为了保证单词的唯一性,不能是把每个单词使用 unicode 转换成数字后相加,*
** 因此需要对每个位置上的单词进行一定的转换*
** 比如:cast 每个字母对应的unicode 分别是 99 97 115 116; 如果单纯的相加,会导致转化的数字会重复*
** 因此 cast 可以这样 99*37^3 + 97*37^2 + 115*37^1 + 116*37^0 这样的数字不会重复;*
** 再次问为什么要用霍纳法则呢?*
** 霍纳法则可以对多项式相加进行化简,提升把字符转化成数字的速度。*
** 1.如果直接使用多项式转化的话,会导致计算量非常大。大概需要 O(2^N)*
** 2.霍纳法则简化后,需要时间复杂度 O(N);
** 为什么hascode初始化值是0?*
** 根据霍纳法则,从最高次数项开始,要保证第一个项系数都要参与运算*
3.完整代码实现
class HasMap {
constructor() {
this.storage
= [];
this.count
= 0;
this.limit
= 7;
}
hasFunc(str
) {
let hascode
= 0;
for (let i
= 0; i
< str
.length
; i
++) {
hascode
= hascode
* 37 + str
.charCodeAt(i
);
}
hascode
= hascode
% this.limit
;
return hascode
;
}
isEmpty() {
return !this.count
;
}
put(key
, val
) {
let hascode
= this.hasFunc(key
);
if (this.storage
[hascode
] == null) {
this.storage
[hascode
] = [{ key
, val
}];
this.count
++;
this.resize();
return;
}
let index
= 0,
chain
= this.storage
[hascode
];
while (index
< chain
.length
) {
if (chain
[index
].key
== key
) {
chain
[index
].val
= val
;
return;
}
index
++;
}
chain
.push({ key
, val
});
this.count
++;
this.resize();
}
get(key
) {
if (this.isEmpty()) return -1;
let hascode
= this.hasFunc(key
);
if (!this.storage
[hascode
]) return -1;
let index
= 0,
chain
= this.storage
[hascode
];
while (index
< chain
.length
) {
if (chain
[index
].key
=== key
) {
return chain
[index
].val
;
}
index
++;
}
return -1;
}
remove(key
) {
if (this.isEmpty()) return -1;
let hascode
= this.hasFunc(key
);
if (this.storage
[hascode
] == null) return -1;
let index
= 0;
while (index
< this.storage
[hascode
].length
) {
if (this.storage
[hascode
][index
].key
== key
) {
return this.storage
[hascode
].splice(index
, 1);
}
index
++;
}
return -1;
}
resize() {
if (this.count
/ this.limit
< 0.75) return;
this.limit
= this.limit
* 2 + 1;
while (!this.isPrime(this.limit
)) {
this.limit
++;
}
let oldStorage
= this.storage
;
this.storage
= [];
this.count
= 0;
let index
= 0;
while (index
< oldStorage
.length
) {
if (oldStorage
[index
]) {
let chainIndex
= 0;
while (chainIndex
< oldStorage
[index
].length
) {
let obj
= oldStorage
[index
][chainIndex
];
this.put(obj
.key
, obj
.val
);
chainIndex
++;
}
}
index
++;
}
console
.log('重新插入成功,当前limit是:%d',this.limit
);
}
isPrime(num
) {
let newNum
= parseInt( Math
.sqrt(num
) );
for (let i
= 2; i
<= newNum
; i
++) {
if (num
% i
== 0) {
return false;
}
}
return true;
}
}
let hastable
= new HasMap();
hastable
.put("lipeng11", { age
: "18", sex
: "男" });
hastable
.put("chen", { age
: "3", sex
: "女" });
console
.log(hastable
.remove("lipeng11"));
console
.log(hastable
.get("lipeng11"));
个人博客地址:点击进入我的个人博客