// ##哈希表
//理论居多,编码较容易
//1.优势:非常快速的插入-删除-查找操作,比树还快
//2.缺点:数据没有顺序,不能以固定的方式来遍历
//3.哈希表究竟是个啥?
//结构就是数组,神奇于下标值的变换-哈希函数,获取HashCode
//将字符串转成下标值
//4.哈希化:将大数字转化为数组范围内下标的过程
//5.哈希表:将最终数据插入数组,进行封装
//6.重复问题:转化下标的过程中会出现下标相同的情况
//7.解决方案一:链地址法-也就是存入数组的是一个数组/链表
//8.解决方案二:开放地址法-继续向下寻找空白位置来放置重复数据
//9.哈希表效率更高:哈希化越好,也就是减少重复,进而要求哈希函数设计的巧妙
//霍纳法则-秦九韶算法:多项式-O(n^2) -> O(n)
//10.哈希函数
function hashFunc(str, size) {
var hashCode = 0;
for(var i = 0; i < str.length; i++) {
hashCode = 37 * hashCode + str.charCodeAt(i);
}
var index = hashCode % size;
return index;
}
//哈希表
function HashTable() {
this.storage = [];
this.count = 0;
this.limit = 7;
HashTable.prototype.hashFunc = function(str, size) {
var hashCode = 0;
for(var i = 0; i < str.length; i++) {
hashCode = 37 * hashCode + str.charCodeAt(i);
}
var index = hashCode % size;
return index;
}
HashTable.prototype.put = function(key, value) {
var index = this.hashFunc(key, this.limit);
var bucket = this.storage[index];
if(bucket == null) {
bucket = [];
this.storage[index] = bucket;
}
for(var i = 0; i < bucket.length; i++) {
var tuple = bucket[i];
if(tuple[0] == key) {
tuple[1] = value;
return true;
}
}
bucket.push([key, value]);
this.count += 1;
}
HashTable.prototype.get = function(key) {
var index = this.hashFunc(key, this.limit);
var bucket = this.storage[index];
if(bucket == null) {
return null;
}
for(var i = 0; i < bucket.length; i++) {
var tuple = bucket[i];
if(tuple[0] == key) {
return tuple[1];
}
}
return null;
}
HashTable.prototype.remove = function(key) {
var index = this.hashFunc(key, this.limit);
var bucket = this.storage[index];
if(bucket == null) {
return null;
}
for(var i = 0; i < bucket.length; i++) {
var tuple = bucket[i];
if(tuple[0] == key) {
bucket.splice(i, 1);
this.count -= 1;
return tuple[1];
}
}
return null;
}
//扩容,装填因子大于0.75,所有数据同时进行修改
HashTable.prototype.resize = function(newLimit) {
var oldStorage = this.storage;
this.storage = [];
this.count = 0;
this.limit = newLimit;
for(var i = 0; i < oldStorage.length; i++) {
var bucket = oldStorage[i];
if(bucket == null) {
continue;
}
for(var j = 0; j < bucket.length; j++) {
var tuple = bucket[j];
this.put(tuple[0], tuple[1]);
}
}
}
//添加操作之后:
if(this.count > this.limit * 0.75) {
this.resize(this.limit * 1);
}
//删除操作之后:
if(this.limit > 7 && this.count < this.limit * 0.25) {
this.resize(Math.floor(this.limit / 2));
}
//质数判断
function isPrime(num) {
var temp = parseInt(Math.sqrt(num));
for(var i = 2; i <= temp; i++) {
if(num % i == 0) {
return false;
}
}
return true;
}
//实现容量恒为质数
HashTable.prototype.getPrime = function(num) {
while(!this.isPrime(num)) {
num += 1;
}
return num;
}
}