Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat : added tries implementation using typescript #150

Merged
merged 7 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions data_structures/tries/test/tries.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Trie } from "../tries";

describe('Trie', () => {
let trie: Trie;

beforeEach(() => {
trie = new Trie();
});

it('should add and find a word', () => {
trie.add('apple');
expect(trie.find('apple')).toBe(true);
});

it('should not find a word that was not added', () => {
trie.add('apple');
expect(trie.find('banana')).toBe(false);
});

it('should not find a partial word', () => {
trie.add('apple');
expect(trie.find('app')).toBe(false);
});

it('should add and find multiple words', () => {
trie.add('apple');
trie.add('banana');
trie.add('cherry');
expect(trie.find('apple')).toBe(true);
expect(trie.find('banana')).toBe(true);
expect(trie.find('cherry')).toBe(true);
});

it('should find words with a common prefix', () => {
trie.add('apple');
trie.add('appetizer');
expect(trie.find('app', true)).toBe(true);
expect(trie.find('app', false)).toBe(false);
});
});
91 changes: 91 additions & 0 deletions data_structures/tries/tries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* Represents a node in a Trie data structure.
*/
class TrieNode {
/**
* An object that stores child nodes for each character in the alphabet.
*/
children: { [key: string]: TrieNode } = {};

/**
* Indicates whether the node represents the end of a word.
*/
isWord: boolean = false;
}

/**
* Trie Data structure for storing and searching words.
*/
export class Trie {
/**
* The root node of the Trie.
*/
root: TrieNode = new TrieNode();

/**
* Creates a new Trie instance.
*/
constructor() {}

/**
* Inserts a word into the Trie.
*
* @param word - The word to insert into the Trie.
*/
private insertNode(node: TrieNode, word: string): void {
for (const char of word) {
if (!node.children[char]) {
node.children[char] = new TrieNode();
}
node = node.children[char];
}
node.isWord = true;
}

/**
* Searches for a word in the Trie.
*
* @param word - The word to search for.
* @param isPrefixMatch - Indicates whether to perform a prefix match (default: false).
* If true, the method returns true if the Trie contains words with the specified prefix.
* If false, the method returns true only if an exact match is found.
* @returns True if the word (or prefix) is found in the Trie; otherwise, false.
*/
public find(word: string, isPrefixMatch: boolean = false): boolean {
return this.searchNode(this.root, word, isPrefixMatch);
}

/**
* Adds a word to the Trie.
*
* @param word - The word to add to the Trie.
* @returns The Trie instance, allowing for method chaining.
*/
public add(word: string): this {
this.insertNode(this.root, word);
return this;
}

/**
* Searches for a word in the Trie.
*
* @param node - The current Trie node being examined.
* @param word - The word to search for.
* @param prefixMatch - Indicates whether to perform a prefix match.
* @returns True if the word (or prefix) is found in the Trie; otherwise, false.
* @private
*/
private searchNode(
node: TrieNode,
word: string,
prefixMatch: boolean
): boolean {
for (const char of word) {
if (!node.children[char]) {
return false;
}
node = node.children[char];
}
return prefixMatch || node.isWord;
}
}