Last active
May 14, 2018 20:47
-
-
Save Cfeusier/5e9c963823a4c2c7567e to your computer and use it in GitHub Desktop.
Hash Table implementation in JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var HashTable = function() { | |
this._limit = 8; // choose any size of hash table bucket limit | |
this._count = 0; | |
this._storage = []; | |
}; | |
HashTable.prototype.insert = function(k, v) { | |
var i = this._getHashIndex(k, this._limit); | |
this._checkLimit(i); // make sure hashidx is in bounds | |
var bucket = this._storage[i]; | |
if (!bucket) { | |
this._storage[i] = []; | |
} | |
var found = false; | |
for (var i = 0; i < bucket.length; i++) { | |
var tuple = bucket[i]; | |
// found matching key | |
if (tuple[0] === k) { | |
// update key with new value | |
tuple[1] = v; | |
found = true; | |
break; | |
} | |
} | |
// no matching key found | |
if (!found) { | |
bucket.push([k,v]); | |
this._count++; | |
if (this._count > this._limit * 0.75) { | |
this._resize(this._limit * 2); | |
} | |
} | |
}; | |
HashTable.prototype.retrieve = function(k) { | |
var i = this._getHashIndex(k, this._limit); | |
this._checkLimit(i); | |
var bucket = this._storage[i]; | |
if (!bucket) { | |
return null; | |
} | |
for (var j = 0; j < bucket.length; j++) { | |
var tuple = bucket[j]; | |
if (tuple[0] === k) { | |
return tuple[1]; | |
} | |
} | |
return null; | |
}; | |
HashTable.prototype.remove = function(k) { | |
var i = this._getHashIndex(k, this._limit); | |
this._checkLimit(i); | |
var bucket = this._storage[i]; | |
if (!bucket) { | |
return null; | |
} | |
for (var j = 0; j < bucket.length; j++) { | |
var tuple = bucket[j]; | |
if (tuple[0] === k) { | |
bucket.splice(j, 1); | |
this._count--; | |
if (this._count < this._limit * 0.25) { | |
this._resize(this._limit / 2); | |
} | |
return tuple[1]; | |
} | |
} | |
return null; | |
}; | |
// private methods _ | |
HashTable.prototype._resize = function(newLimit) { | |
var oldStorage = this._storage; | |
this._storage = []; | |
this._limit = newLimit; | |
this._count = 0; | |
for (var j = 0; j < oldStorage.length; j++) { | |
var bucket = oldStorage[j]; | |
if (!bucket) break; | |
for (var i = 0; i < bucket.length; i++) { | |
var tuple = bucket[i]; | |
this.insert(tuple[0], tuple[1]); | |
} | |
} | |
}; | |
HashTable.prototype._getHashIndex = function(str, max) { | |
var hash = 0; | |
for (var i = 0; i < str.length; i++) { | |
hash = (hash<<5) + hash + str.charCodeAt(i); | |
hash = hash & hash; | |
hash = Math.abs(hash); | |
} | |
return hash % max; | |
}; | |
HashTable.prototype._checkLimit = function(index) { | |
if (typeof index !== 'number') { | |
throw new Error('first argument of setter must be a numeric index'); | |
} | |
if (limit <= index) { | |
throw new Error('out-of-bounds index cannot be accessed'); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment