
A Trie (pronounced “try”) is a specialized tree-like data structure used to store strings efficiently, especially for operations like searching, inserting, and deleting prefixes. It is commonly called a prefix tree because it enables fast prefix-based lookups.
Tries are widely used in autocomplete systems, spell checkers, dictionary implementations, and IP routing tables.
Each Trie node contains:
For example, storing “car”, “cat”, and “bat” in a Trie looks like this:
(root)
/ \
c b
/ \ \
a a a
/ \ \
r t t
class TrieNode:
def __init__(self):
self.children = {} # Dictionary to store children nodes
self.is_end_of_word = False # Marks if this node is the end of a word
class Trie:
def __init__(self):
self.root = TrieNode() # Initialize Trie with an empty root node
def insert(self, word):
node = self.root
for char in word:
if char not in node.children:
node.children[char] = TrieNode() # Create a new node if character not found
node = node.children[char]
node.is_end_of_word = True # Mark the last node as end-of-word
def search(self, word):
node = self.root
for char in word:
if char not in node.children:
return False # If a character is missing, word does not exist
node = node.children[char]
return node.is_end_of_word # Check if the last node is marked as end-of-word
def starts_with(self, prefix):
node = self.root
for char in prefix:
if char not in node.children:
return False
node = node.children[char]
return True # Prefix exists in Trie
def delete(self, word):
def _delete(node, word, depth):
if depth == len(word):
if not node.is_end_of_word:
return False # Word not found
node.is_end_of_word = False
return len(node.children) == 0 # If node has no children, delete it
char = word[depth]
if char not in node.children:
return False # Word not found
should_delete = _delete(node.children[char], word, depth + 1)
if should_delete:
del node.children[char]
return len(node.children) == 0 # If no children left, delete node
return False
_delete(self.root, word, 0)
# Example Usage
trie = Trie()
trie.insert("car")
trie.insert("cat")
trie.insert("bat")
print(trie.search("car")) # True
print(trie.search("bat")) # True
print(trie.search("can")) # False
print(trie.starts_with("ca")) # True
trie.delete("car")
print(trie.search("car")) # False
import java.util.HashMap;
import java.util.Map;
class TrieNode {
Map<Character, TrieNode> children = new HashMap<>();
boolean isEndOfWord = false;
}
class Trie {
private TrieNode root;
public Trie() {
root = new TrieNode();
}
public void insert(String word) {
TrieNode node = root;
for (char ch : word.toCharArray()) {
node.children.putIfAbsent(ch, new TrieNode());
node = node.children.get(ch);
}
node.isEndOfWord = true;
}
public boolean search(String word) {
TrieNode node = root;
for (char ch : word.toCharArray()) {
if (!node.children.containsKey(ch)) {
return false;
}
node = node.children.get(ch);
}
return node.isEndOfWord;
}
public boolean startsWith(String prefix) {
TrieNode node = root;
for (char ch : prefix.toCharArray()) {
if (!node.children.containsKey(ch)) {
return false;
}
node = node.children.get(ch);
}
return true;
}
public void delete(String word) {
delete(root, word, 0);
}
private boolean delete(TrieNode node, String word, int depth) {
if (depth == word.length()) {
if (!node.isEndOfWord) {
return false;
}
node.isEndOfWord = false;
return node.children.isEmpty();
}
char ch = word.charAt(depth);
if (!node.children.containsKey(ch)) {
return false;
}
boolean shouldDelete = delete(node.children.get(ch), word, depth + 1);
if (shouldDelete) {
node.children.remove(ch);
return node.children.isEmpty();
}
return false;
}
public static void main(String[] args) {
Trie trie = new Trie();
trie.insert("car");
trie.insert("cat");
trie.insert("bat");
System.out.println(trie.search("car")); // true
System.out.println(trie.search("bat")); // true
System.out.println(trie.search("can")); // false
System.out.println(trie.startsWith("ca")); // true
trie.delete("car");
System.out.println(trie.search("car")); // false
}
}
A Trie is a powerful data structure for storing and searching strings efficiently. Its fast lookup time and prefix search capabilities make it ideal for text processing, networking, and dictionary-based applications. However, it may consume more memory than hash tables, especially in naive implementations.
For memory-efficient alternatives, compressed tries and Radix trees can be used.
When analyzing a stock, one of the first financial indicators you’ll encounter is EPS, or Earnings Per Share. It’s one… Read More
When you look at a stock’s profile on a financial website, one of the first things you’ll see is its… Read More
In the world of open-source software, simplicity and flexibility are often just as important as legal protection. That’s why the… Read More
If you want your software to be open source, but still compatible with commercial use—and not as restrictive as the… Read More
When it comes to open-source software, developers and businesses alike need licenses that balance freedom, legal clarity, and long-term security.… Read More
If you’re working on open-source projects or choosing third-party libraries for your software, understanding software licenses is essential. Among the… Read More