<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>leecode</title>
</head>
<body>
<script>
function HashTable(){
//this.storage = []; // 存放元素的数组
this.count = 0; // 表示当前已经存在了多少数据
this.limit = 7; // 用于标记数组中一共可以存放多少个元素,为质数
this.storage = new Array(this.limit).fill(0).map(() => new Array());
// 实现哈希函数
// 1. 将字符串转换为较大的数字:hashCode
// 2. 将数字hashCode压缩到数组范围之内
HashTable.prototype.hashfun = function(str,size){
var hashCode = 0;
// 霍纳法则公式
for (let i = 0; i < str.length; i++) {
// string.charCodeAt(index): 返回字符串index位字符的Unicode 编码
// 相当于霍纳法则里的:anx+an-1
// ((...(((anx+an-1)x+an-2)x+an-3)...)x+a1)x+a0
// 37是一个质数,也可以写其他质数,质数比较常用37
hashCode = 37 * hashCode + str.charCodeAt(i);
}
// 取余
var index = hashCode % size;
return index;
}
// 插入&修改操作
HashTable.prototype.set = function(key, value){
// 1. 根据key获取对应的hashcode,也就是数组的下标
var index = this.hashfun(key, this.limit);
// 2. 根据index取出对应的bucket
var bucket = this.storage[index];
// 3. 查看`bucket`是否为`null`
if (bucket == null) {
// 如果为空,就创建一个数组,存放到index位置
bucket = [];
this.storage[index] = bucket;
}
// 4. 判断是否是修改数据
for (let i = 0; i < bucket.length; i++) {
// 定义一个数组存放bucket里的元素
var tuple = bucket[i];
if (tuple[0] == key) {
tuple[1] = value;
return;
}
}
// 5.添加
bucket.push([key,value]);
this.count += 1;
// 6. 判断是否需要扩容
if (this.count > this.limit * 0.75) {
var newSize = this.limit * 2;
var newPrime = this.getPrime(newSize);
this.resize(newPrime);
}
}
// 获取操作
HashTable.prototype.get = function(key){
// 1. 通过传来的key获取hashCode,查找到对应的元素
var index = this.hashfun(key,this.limit);
// 2. 根据index取出对应的bucket
var bucket = this.storage[index];
// 3. 判断bucket是否为空
if (bucket == null) return null;
// 4. 查找元素
for (let i = 0; i < bucket.length; i++) {
var tuple = bucket[i];
if (tuple[0] == key) {
return tuple[1];
}
return null;
}
}
// 删除操作
HashTable.prototype.delete = function(key){
// 1. 通过传来的key获取hashCode,查找到对应的元素
var index = this.hashfun(key,this.limit);
// 2. 根据index取出对应的bucket
var bucket = this.storage[index];
// 3. 判断bucket是否为空
if (bucket == null) return null;
// 4. 查找元素
for (let i = 0; i < bucket.length; i++) {
var tuple = bucket[i];
if (tuple[0] == key) {
bucket.splice(i,1);
this.count--;
return tuple[1];
// 判断是否需要减小容量
if (this.limit > 7 && this.count < this.limit * 0.25) {
var newSize = Math.floor(this.limit / 2);
var newPrime = this.getPrime(newSize);
this.resize(newPrime);
}
}
}
return null;
}
// 判断哈希表是否为空
HashTable.prototype.isEmpty = function(){
return this.count == 0;
}
// 获取哈希表中的元素个数
HashTable.prototype.size = function(){
return this.count;
}
// 哈希表扩容
HashTable.prototype.resize = function(newLimit){
// 1. 保存旧的数组内容
var oldStorage = this.storage;
// 2. 重置所有属性
this.limit = newLimit;
this.storage = new Array(this.limit).fill(0).map(() => new Array());
this.count = 0;
// 3. 遍历oldStorage
for (let i = 0; i < oldStorage.length; i++) {
// 3.1 取出对应的bucket
var bucket = oldStorage[i];
// 3.2 判断bucket是否为null
if (bucket == null) {
continue;
}
// 3.3 bucket中有数据,那么取出数据,重新插入
for (let i = 0; i < bucket.length; i++) {
var tuple = bucket[i];
this.set(tuple[0], tuple[1]);
}
}
}
// 判断某个数字是否是质数
HashTable.prototype.isPrime = function (num){
var temp = parseInt(Math.sqrt(num));
for (let i = 0; i <= temp; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
// 获取质数
HashTable.prototype.getPrime = function(num){
while(this.getPrime(num)){
num++;
}
return num;
}
}
// var romanToInt = function(s) {
// var roman = new HashTable();
// roman.set('I', 1);
// roman.set('V', 5);
// roman.set('X', 10);
// roman.set('L', 50);
// roman.set('C', 100);
// roman.set('D', 500);
// roman.set('M', 1000);
// var sum = 0;
// var n = s.length;
// for (let i = 0; i < n; i++) {
// var value = roman.get(s[i]);
// if (i < n-1 && value < roman.get(s[i+1])) {
// sum -= value;
// }else{
// sum += value;
// }
// }
// return sum;
// };
// console.log(romanToInt("III")); // 3
// console.log(romanToInt("IV")); // 5
// console.log(romanToInt("IX")); // 9
// console.log(romanToInt("LVIII")); //58
// console.log(romanToInt("CD")); // 400
var hash = new HashTable();
hash.set(1,123);
hash.set(2,234);
console.log(hash.delete(2));
</script>
</body>
</html>
JavaScript - 不使用任何内建的哈希表库设计一个哈希映射(HashMap)
最新推荐文章于 2021-07-01 15:19:39 发布