Created
January 31, 2019 10:38
-
-
Save rxluz/43853c4f2859c7a2ef108da2bf57f23d to your computer and use it in GitHub Desktop.
JS Data Structures: Hash tables, see more at: https://medium.com/p/e3c229ecaacb
This file contains hidden or 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
function LinkedList() { | |
let head = null | |
let size = 0 | |
class Utils { | |
static node(element) { | |
return { | |
element, | |
next: null, | |
} | |
} | |
static handleElement(element) { | |
if (typeof element !== 'string') { | |
return JSON.stringify(element) | |
} else { | |
return element | |
} | |
} | |
} | |
class PublicLinkedList { | |
append(element) { | |
let current = this.getHead() | |
let node = Utils.node(element) | |
if (this.isEmpty()) { | |
head = node | |
size++ | |
return true | |
} | |
while (current && current.next) { | |
current = current.next | |
} | |
current.next = node | |
size++ | |
} | |
remove(elem) { | |
let element = Utils.handleElement(elem) | |
let current = this.getHead() | |
if (Utils.handleElement(current.element) === element) { | |
head = current.next | |
size-- | |
return true | |
} | |
let previous = null | |
while (current && Utils.handleElement(current.element) !== element) { | |
previous = current | |
current = current.next | |
} | |
if ( | |
previous && | |
current && | |
Utils.handleElement(current.element) === element | |
) { | |
previous.next = current.next | |
size-- | |
return true | |
} | |
return false | |
} | |
size() { | |
return size | |
} | |
isEmpty() { | |
return this.size() === 0 | |
} | |
getHead() { | |
return head | |
} | |
} | |
return new PublicLinkedList() | |
} | |
function HashTable() { | |
let table = [] | |
let size = 0 | |
class Utils { | |
static item(key, value) { | |
return { | |
key, | |
value, | |
toString: () => `['${key}', '${value}']`, | |
} | |
} | |
static addComma(content) { | |
return content !== '' ? ', ' : '' | |
} | |
static djb2(key) { | |
let hash = 5381 | |
let keyChars = key.split('') | |
keyChars.forEach(chr => { | |
hash = hash * 33 + chr.charCodeAt(0) | |
}) | |
return hash % 1013 | |
} | |
} | |
class PublicHashTable { | |
put(key, value) { | |
const index = Utils.djb2(key) | |
if (!table[index]) table[index] = new LinkedList() | |
let current = table[index].getHead() | |
while (current && current.element && current.element.key !== key) { | |
current = current.next | |
} | |
if (current && current.element && current.element.key === key) { | |
table[index].remove(current.element) | |
} else { | |
size++ | |
} | |
let item = Utils.item(key, value) | |
table[index].append(item) | |
return true | |
} | |
remove(key) { | |
const index = Utils.djb2(key) | |
if (this.isEmpty() || !table[index]) return false | |
let current = table[index].getHead() | |
while (current && current.element && current.element.key !== key) { | |
current = current.next | |
} | |
if (current && current.element && current.element.key === key) { | |
table[index].remove(current.element) | |
size-- | |
return true | |
} | |
return false | |
} | |
has(key) { | |
const index = Utils.djb2(key) | |
if (this.isEmpty() || !table[index]) return false | |
let current = table[index].getHead() | |
while (current && current.element && current.element.key !== key) { | |
current = current.next | |
} | |
if (current && current.element && current.element.key === key) return true | |
return false | |
} | |
get(key) { | |
const index = Utils.djb2(key) | |
if (this.isEmpty() || !table[index]) return undefined | |
let current = table[index].getHead() | |
while (current && current.element && current.element.key !== key) { | |
current = current.next | |
} | |
if (current && current.element && current.element.key === key) | |
return current.element.value | |
return undefined | |
} | |
values() { | |
let allValues = [] | |
if (this.isEmpty()) return allValues | |
table.forEach(item => { | |
let current = item.getHead() | |
while (current && current.element) { | |
allValues.push(current.element.value) | |
current = current.next | |
} | |
}) | |
return allValues | |
} | |
keys() { | |
let allKeys = [] | |
if (this.isEmpty()) return allKeys | |
table.forEach(item => { | |
let current = item.getHead() | |
while (current && current.element) { | |
allKeys.push(current.element.value) | |
current = current.next | |
} | |
}) | |
return allKeys | |
} | |
toString() { | |
let content = '' | |
if (this.isEmpty()) return content | |
table.forEach(item => { | |
let current = item.getHead() | |
while (current && current.element) { | |
const comma = Utils.addComma(content) | |
content += `${comma}${current.element.toString()}` | |
current = current.next | |
} | |
}) | |
return content | |
} | |
size() { | |
return size | |
} | |
isEmpty() { | |
return this.size() === 0 | |
} | |
clear() { | |
table = [] | |
size = 0 | |
} | |
} | |
return new PublicHashTable() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment