Skip to content

Instantly share code, notes, and snippets.

@mikews93
Created February 20, 2021 05:36
Show Gist options
  • Save mikews93/cefd29440acbe6a2a16cdc0907b47231 to your computer and use it in GitHub Desktop.
Save mikews93/cefd29440acbe6a2a16cdc0907b47231 to your computer and use it in GitHub Desktop.
Basic implementation of Trie data structure
interface searchOptions {
showHoleWord?: boolean;
}
class trieNode {
public word: string;
public children;
public isWord: boolean;
constructor(word: string) {
this.word = word;
this.children = {};
this.isWord = false;
}
}
class Trie {
private root: trieNode;
constructor(words?: string[]) {
this.root = new trieNode('');
this.addManyWords(words);
}
/**
* @description inserts a words in the trie
* @param word
* @param previewsNode
*/
private insertWord (word:string, previewsNode = this.root): boolean {
if (!word) {
return previewsNode.isWord = true;
}
const splicedWord = word.split('');
const firstLetter = splicedWord.shift();
if (!previewsNode.children[firstLetter]) {
previewsNode.children[firstLetter] = new trieNode(firstLetter)
}
this.insertWord(splicedWord.join(''), previewsNode.children[firstLetter]);
}
/**
* @description Adds individual words to the trie
* @param word
*/
public addWord(word: string): boolean {
return this.insertWord(word);
}
/**
* @description Adds several words in the trie at once
* @param words string array of words
*/
public addManyWords(words: string[] = []): void {
words.forEach((word) => this.insertWord(word))
}
/**
* @description returns the words that starts with the given prefix
* @param prefix string from which the matches should start with
*
* @returns array of strings with matching words
*/
public searchPrefix(prefix: string, searchOptions: searchOptions = { showHoleWord: true }): string[] {
if (!prefix.length|| !Object.keys(this.root.children).length) {
return [];
}
let initNode: trieNode = this.root
let prefixCopy = prefix;
const matches: string[] = []
do {
const splicedWord = prefixCopy.split('');
const firstLetter = splicedWord.shift();
prefixCopy = splicedWord.join('');
initNode = initNode.children[firstLetter];
if (prefixCopy.length == 0 && initNode) {
this.assembleWords(initNode, searchOptions.showHoleWord ? prefix : '', matches);
}
} while (prefixCopy.length > 0 || initNode !== undefined)
return matches;
}
/**
* @description Iterates over the trie and reconstructs the words
* @param partialTrie initial node to start iterating
* @param assembleLetters reconstructed word
* @param matches array of matches found
*/
private assembleWords(partialTrie: trieNode, assembleLetters: string, matches: string[]) {
if (partialTrie.isWord){
matches.push(assembleLetters);
}
Object.keys(partialTrie.children).forEach((key) => {
this.assembleWords(partialTrie.children[key], assembleLetters.concat(partialTrie.children[key].word), matches);
})
}
};
const parkList = ['Acadia', 'American Samoa', 'Arches', 'Badlands', 'Big Bend', 'Glacier', 'Glacier Bay', 'Glacier Baywatch', 'Grand Theft Auto', 'Halo', 'Cartagena', 'Medellin', 'Night City'];
const myTrie = new Trie(parkList)
console.log( {finds: myTrie.searchPrefix('Gla'), autoCompletes: myTrie.searchPrefix('A', { showHoleWord: false }) });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment