Skip to content

Instantly share code, notes, and snippets.

@khaled0fares
Last active September 17, 2016 20:26
Show Gist options
  • Save khaled0fares/4e93109a8b925b3207b0d03368d6a87e to your computer and use it in GitHub Desktop.
Save khaled0fares/4e93109a8b925b3207b0d03368d6a87e to your computer and use it in GitHub Desktop.
Hash table implementation in JS
let LinkedList = require('./linked_list');
class HashTable{
constructor(size){
this.table = new Array(size);
}
_setup(key, index,head){
let obj = {};
obj[key] = head;
this.table[index] = new LinkedList(obj);
}
_hash(key){
let total = 0, key_len = key.length,table_len = this.table.length;
const HORNER_CONSTANT = 37;
for(let i = 0; i < key_len; i++){
total += total * HORNER_CONSTANT + key.charCodeAt(i);
}
return total % table_len;
}
_list(key){
let index = this._hash(key);
return this.table[index];
}
put(key, val){
if(this.get(key)){return false;}
let index = this._hash(key), list = this.table[index];
if(this.table[index] != undefined && this.table[index].head != null){
let obj = {};
obj[key] = val;
list.insertWithIndex(0,obj);
}else{
this._setup(key, index, val);
}
}
get(key){
let ele = this._list(key);
if(ele != undefined){
let node = ele.findByKey(key);
return node.val[key];
}
}
update(key, val){
let ele = this._list(key)
if(ele != undefined){
return ele.updateByKey(key, val);
}
}
remove(key){
let ele = this._list(key)
if(ele != undefined){
ele.removeByKey(key)
}
}
displayAll(){
let i = 0, len = this.table.length;
for(i; i < len; i++){
let ele = this.table[i];
if(ele != undefined){
ele.displayByKey();
}
}
}
}
class Node{
constructor(val){
this.val = val;
this.next = null
}
}
module.exports = class LinkedList{
constructor(valOfHead){
this.head = new Node(valOfHead);
this.length = 1;
}
exist(val){
return !!this.find(val);
}
find(val){
let currentNode = this.head;
while(currentNode != null){
if(currentNode.val == val){
return currentNode;
}
currentNode = currentNode.next;
}
return false;
}
findByKey(key){
let currentNode = this.head;
while(currentNode != null){
if(key in currentNode.val){
return currentNode;
}
currentNode = currentNode.next;
}
return false;
}
updateByKey(key, val){
let currentNode = this.head;
while(currentNode != null){
if(key in currentNode.val){
currentNode.val[key] = val;
}
currentNode = currentNode.next;
}
return false;
}
insert(newElement, afterElement){
let newNode = new Node(newElement);
let afterNode = this.find(afterElement);
if(afterNode == false){console.log(`Element ${afterElement} doesn't exist`);return false;}
this.length += 1;
newNode.next = afterNode.next;
afterNode.next = newNode;
}
findPreviousNode(val){
if(!this.exist(val)){console.log(`Element ${val} doesn't exist`);return false;}
let current = this.head;
while(current.next && current.next.val != val){
current = current.next;
}
return current;
}
remove(val){
//Element doesn't exist
if(!this.exist(val)){console.log(`Element ${val} doesn't exist`);return false};
let removed = this.find(val);
//Element we want to remove is the first elment in the list
if(this.head.val == val){
this.head = this.head.next;
}
//element exists But it's not the head element so we will remove it using it's previous node.
else{
let prevNode = this.findPreviousNode(val);
prevNode.next = removed.next;
}
this.length -= 1;
return true;
}
findPreviousNodeByKey(key){
let current = this.head;
while(current.next && key in current.next.val){
current = current.next;
}
return current;
}
removeByKey(key){
let removed = this.findByKey(key);
//Element we want to remove is the first elment in the list
if(key in this.head.val){
this.head = this.head.next;
}
//element exists But it's not the head element so we will remove it using it's previous node.
else{
let prevNode = this.findPreviousNodeByKey(key);
prevNode.next = removed.next;
}
this.length -= 1;
return true;
}
existWithIndex(index){return index < this.length && index >= 0;}
findByIndex(index){
if(!this.existWithIndex(index)){console.log(`No node with Index ${index}`);return false;}
let currentNode = this.head;
let init = 0;
while(currentNode && init < index){
currentNode = currentNode.next;
init += 1;
}
return currentNode;
}
insertWithIndex(index,item){
let newNode = new Node(item);
//Element doesn't exist
if( !this.existWithIndex(index) ){ console.log(`Element with index ${index} doesn't exist`); return false;}
//Insert in the first position
if(index == 0){
newNode.next = this.head;
this.head = newNode;
}else{
//Insert between two nodes
let currentNode = this.findByIndex(index);
let prevNode = this.findPreviousNode(currentNode.val);
newNode.next = currentNode;
prevNode.next = newNode;
}
this.length += 1;
return true;
}
removeWithIndex(index){
// if element doesn't exist
if(!this.existWithIndex(index)){console.log(`No element with index ${index} to be removed`);return false;}
// if it's the firts element in the list
if(index == 0){this.head = this.head.next;}
else{
let removed = this.findByIndex(index);
let prevNode = this.findPreviousNode(removed.val);
prevNode.next = removed.next;
}
this.length -= 1;
return true;
}
displayByKey(){
let current = this.head;
while(current){
for(let key in current.val){
console.log(`${key} -> ${current.val[key]}` );
}
current = current.next;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment