Created
June 19, 2023 15:04
-
-
Save waterrmalann/61e63065a3834e0a5f2b8a9b5c494019 to your computer and use it in GitHub Desktop.
A simple JavaScript implementation of Trie data structure.
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
// An implementation of a Trie Data Structure | |
// - All letters are assumed to be lowercase english alphabets. | |
class Node { | |
constructor(value) { | |
// We store a character as the value. | |
this.value = value; | |
// A marker for if the node signifies an end of a word. | |
this.isEndofWord = false; | |
// The 26 (lowercase alphabet) children node links. | |
this.children = new Array(26); | |
} | |
} | |
class Trie { | |
constructor() { | |
// We init an empty root node. | |
this.root = new Node(''); | |
} | |
insert(word) { | |
// Insert a word, character-by-character into the Trie. | |
let current = this.root; | |
// We loop through all the characters of the word. | |
for (let i = 0; i < word.length; i++) { | |
// Grab the array index for the character. | |
let charIndex = word.charCodeAt(i) - 97; | |
// If an element does not exist at our index. | |
if (!current.children[charIndex]) { | |
// We place the new node there for the letter. | |
current.children[charIndex] = new Node(word[i]); | |
} | |
// We advance the current pointer. | |
current = current.children[charIndex]; | |
} | |
// We mark the final node as end of word. | |
current.isEndofWord = true; | |
} | |
_getNode(word) { | |
// Helper function to get the node at the end of a word. | |
let current = this.root; | |
// We loop through all the characters. | |
for (let i = 0; i < word.length; i++) { | |
// Grab the array index for the character. | |
let charIndex = word.charCodeAt(i) - 97; | |
// If an element does not exist at our index. | |
if (!current.children[charIndex]) { | |
return null; | |
} | |
// Otherwise, we advance the current pointer. | |
current = current.children[charIndex]; | |
} | |
// Return the last node we safely encountered. | |
return current; | |
} | |
startsWith(word) { | |
// Determine whether we have anything that starts with a word in our Trie. | |
// Call our helper function to get the node(?) at the end of the word. | |
let node = this._getNode(word); | |
// We coerce it into a boolean and return that. | |
return !!node; | |
} | |
search(word) { | |
// Return whether a word exists in our Trie or not. | |
// Call our helper function get the last node(?) at the end of the word. | |
let node = this._getNode(word); | |
// We have to make sure the node is not null, but also that the node is an end of word. | |
return (node && node.isEndofWord); | |
} | |
allWords() { | |
// Return all the words from our Trie. | |
// Create an array to hold the words. | |
let words = []; | |
// Call the helper function from the root, | |
// given an empty string to construct and `words` array to push to. | |
this._findAllWords(this.root, '', words); | |
// Return the words array. | |
return words; | |
} | |
_findAllWords(node, prefix, words) { | |
// As long as the node exists. | |
if (node) { | |
// If the node is an end of the word, | |
if (node.isEndofWord) { | |
// We push the prefix to the array. | |
words.push(prefix); | |
} | |
// Loop over the children of the the node. | |
for (let i = 0; i < node.children.length; i++) { | |
// If the node exists. | |
if (node.children[i]) { | |
// Recursively call the function on the child, by adding to the prefix. | |
this._findAllWords(node.children[i], prefix + node.children[i].value, words); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment