What is a Trie (Prefix Tree)?
Updated Apr 28, 2026
Short answer
A Trie, also called a Prefix Tree, is a tree-based data structure used to store and search strings efficiently by storing characters along paths from the root. Each node represents a character, and paths from the root represent prefixes or complete words. Tries are commonly used for autocomplete, dictionary lookups, spell checking, and prefix-based searching.
Deep explanation
A Trie stores a collection of strings by breaking each string into individual characters. Unlike a binary search tree or hash table, a Trie organizes data based on the characters themselves, allowing fast prefix operations.
For example, storing the words:
catcarcaredogwould create a structure like:
root / \ c d | | a o / \ | t r g | eEach path from the root represents a sequence of characters:
c -> a -> trepresents"cat"c -> a -> rrepresents"car"c -> a -> r -> erepresents"care"
The final node of a complete word is usually marked with a flag such as isWord = true to distinguish between a complete word and just a prefix.
For example, after inserting "app":
root | a | p | p (end of word)The node containing the second p represents both:
- The complete word
"app" - A prefix of words like
"apple"and"application"
Main Operations
1. Insertion
To insert a word:
- Start from the root.
- Check whether a child node exists for each character.
- Create missing nodes.
- Mark the last node as the end of the word.
Example:
def insert(word): node = root
for char in word: if char not in node.children: node.children[char] = TrieNode()
node = node.children[char]
node.is_word = TrueThe time complexity is:
O(L)where L is the length of the inserted word.
2. Search
To search for a word, the Trie follows the character path from the root.
For example, searching for "car":
root -> c -> a -> rIf every character exists and the final node is marked as a complete word, the search succeeds.
The time complexity is:
O(L)3. Prefix Search
One of the biggest advantages of a Trie is efficient prefix searching.
For example, finding all words beginning with "ca" only requires reaching:
root -> c -> aThen the Trie can explore all descendants of that node.
This makes Tries useful for features like:
- Search autocomplete
- Type-ahead suggestions
- Word prediction
Trie Node Structure
A typical Trie node contains:
class TrieNode: def __init__(self): self.children = {} self.is_word = FalseEach node stores:
- A collection of child nodes.
- A marker indicating whether the node completes a valid word.
Advantages of Tries
- Fast insertion and lookup based on word length.
- Efficient prefix searching.
- Avoids repeated string comparisons.
- Naturally represents relationships between words with shared prefixes.
Disadvantages of Tries
- Can use a lot of memory because every node stores references to children.
- More complex to implement compared with hash tables.
- Not always the best choice when only exact lookups are needed.
Trie vs Hash Table
A hash table provides average O(1) lookup for exact words:
Find "apple" -> direct hash lookupA Trie provides O(L) lookup:
Find "apple" -> a -> p -> p -> l -> eHowever, Tries have an important advantage: they can efficiently answer prefix-based questions, such as "find all words starting with app."
Real-world example
A search engine's autocomplete feature can use a Trie to suggest words as a user types.
Suppose the Trie contains:
appleapplicationappbananaWhen a user types:
appthe Trie quickly reaches the node:
root -> a -> p -> pThen it can return all words stored below that node:
appappleapplicationA simple implementation:
class TrieNode: def __init__(self): self.children = {} self.is_word = False
class Trie: def __init__(self): self.root = TrieNode()
def insert(self, word): node = self.root
for char in word: if char not in node.children: node.children[char] = TrieNode()
node = node.children[char]
node.is_word = True
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 TrueThe starts_with operation only needs to check the characters in the prefix, making it efficient for autocomplete systems.
Common mistakes
- * Thinking a Trie stores complete words inside every node instead of storing characters.
- * Assuming Trie search complexity is `O(N)` because it contains `N` words.
- * Forgetting to mark the end of a word and confusing prefixes with complete words.
- * Using a Trie when only exact lookups are needed and a hash table would be simpler.
- * Ignoring the memory cost caused by many Trie nodes and child references.
- * Confusing a Trie with a binary tree because a Trie can have many children per node.
Follow-up questions
- What is the time complexity of searching for a word in a Trie?
- Why is a Trie useful for autocomplete systems?
- How is a Trie different from a binary search tree?
- What are the main disadvantages of using a Trie?
- How can you optimize the memory usage of a Trie?