javascript-algorithms-and-data-structures
Version:
Algorithms and data-structures implemented on JavaScript
99 lines (84 loc) • 2.41 kB
JavaScript
import LinkedList from '../linked-list/LinkedList';
// Hash table size directly affects on the number of collisions.
// The bigger the hash table size the less collisions you'll get.
// For demonstrating purposes hash table size is small to show how collisions
// are being handled.
const defaultHashTableSize = 32;
export default class HashTable {
/**
* @param {number} hashTableSize
*/
constructor(hashTableSize = defaultHashTableSize) {
// Create hash table of certain size and fill each bucket with empty linked list.
this.buckets = Array(hashTableSize).fill(null).map(() => new LinkedList());
// Just to keep track of all actual keys in a fast way.
this.keys = {};
}
/**
* Converts key string to hash number.
*
* @param {string} key
* @return {number}
*/
hash(key) {
const hash = Array.from(key).reduce(
(hashAccumulator, keySymbol) => (hashAccumulator + keySymbol.charCodeAt(0)),
0,
);
// Reduce hash number so it would fit hash table size.
return hash % this.buckets.length;
}
/**
* @param {string} key
* @param {*} value
*/
set(key, value) {
const keyHash = this.hash(key);
this.keys[key] = keyHash;
const bucketLinkedList = this.buckets[keyHash];
const node = bucketLinkedList.find({ callback: nodeValue => nodeValue.key === key });
if (!node) {
// Insert new node.
bucketLinkedList.append({ key, value });
} else {
// Update value of existing node.
node.value.value = value;
}
}
/**
* @param {string} key
* @return {*}
*/
delete(key) {
const keyHash = this.hash(key);
delete this.keys[key];
const bucketLinkedList = this.buckets[keyHash];
const node = bucketLinkedList.find({ callback: nodeValue => nodeValue.key === key });
if (node) {
return bucketLinkedList.delete(node.value);
}
return null;
}
/**
* @param {string} key
* @return {*}
*/
get(key) {
const bucketLinkedList = this.buckets[this.hash(key)];
const node = bucketLinkedList.find({ callback: nodeValue => nodeValue.key === key });
return node ? node.value.value : undefined;
}
/**
* @param {string} key
* @return {boolean}
*/
has(key) {
return Object.hasOwnProperty.call(this.keys, key);
}
/**
* @return {string[]}
*/
getKeys() {
return Object.keys(this.keys);
}
}