1. Home
  2. Data Structures
  3. Trie (Prefix Tree)

Trie (Prefix Tree)

A tree that stores words letter by letter, so words with the same beginning share a path. The secret behind autocomplete.

Interactive 3DIntermediate11 min readDSAUpdated

Drag to rotate · Right-drag to pan · Click, then scroll to zoom · Space play · ←→ step

What's happening

Pseudocode

    Try this in the 3D model

    • Press Starts with… with "ca". Which words light up?
    • Insert "card". How many new nodes were created? Why so few?
    • Search for "ca". It exists as a path — so why is it "not found"?
    • Insert a word that shares nothing with the others, like "zebra".

    What is a trie?

    A trie (pronounced “try”, from retrieval) is a tree for storing strings. Each edge represents one letter. A word is spelled by the path from the root down to a node marked end-of-word.

    Words that begin the same way share the same path. In the model, “car”, “cart” and “care” all go through c → a → r.

    Analogy: a paper dictionary’s thumb index. To find “carrot” you go to the C section, then the CA pages, then CAR… Each letter narrows the search.

    Structure of a node

    Each node stores:

    • its children — one per possible next letter (an array of 26, or a hash map),
    • an isEnd flag — true if a word finishes here.

    The root is empty; it represents the empty prefix.

    Operations

    Insert(word): start at the root. For each letter, follow the child for that letter — creating it if missing. At the end, set isEnd = true.

    Search(word): follow the letters. If any letter is missing → not found. If you reach the end, the answer is the node’s isEnd flag. (That’s why searching “ca” fails even though the path exists: no word ends there.)

    StartsWith(prefix): follow the prefix, then collect every word in the subtree below. That’s autocomplete.

    Delete(word): unset isEnd, then remove nodes bottom-up that have no children and aren’t the end of another word.

    Why is it fast?

    Every operation walks one node per letter, so it costs O(L) where L is the word length — independent of how many words are stored. A balanced BST of strings needs O(L · log n) because each comparison of two strings can take L steps.

    The cost is memory: each node may hold up to 26 child pointers. Compressed tries (radix trees) merge chains of single children to save space.

    Code

    class TrieNode:
        def __init__(self):
            self.children = {}      # letter -> TrieNode
            self.is_end = False
    
    class Trie:
        def __init__(self):
            self.root = TrieNode()
    
        def insert(self, word):
            node = self.root
            for ch in word:
                node = node.children.setdefault(ch, TrieNode())
            node.is_end = True
    
        def _walk(self, s):
            node = self.root
            for ch in s:
                node = node.children.get(ch)
                if node is None:
                    return None
            return node
    
        def search(self, word):
            node = self._walk(word)
            return node is not None and node.is_end
    
        def starts_with(self, prefix):
            node = self._walk(prefix)
            out = []
            def collect(n, acc):
                if n.is_end:
                    out.append(acc)
                for ch, child in sorted(n.children.items()):
                    collect(child, acc + ch)
            if node:
                collect(node, prefix)
            return out
    
    t = Trie()
    for w in ["car", "cat", "cart", "care", "dog", "dot", "do"]:
        t.insert(w)
    print(t.search("car"), t.search("ca"))   # True False
    print(t.starts_with("ca"))               # ['car', 'care', 'cart', 'cat']
    #include <iostream>
    #include <string>
    using namespace std;
    
    struct Node {
        Node* child[26] = {};
        bool isEnd = false;
    };
    
    void insert(Node* root, const string& w) {
        Node* n = root;
        for (char c : w) {
            int i = c - 'a';
            if (!n->child[i]) n->child[i] = new Node();
            n = n->child[i];
        }
        n->isEnd = true;
    }
    
    bool search(Node* root, const string& w) {
        Node* n = root;
        for (char c : w) {
            n = n->child[c - 'a'];
            if (!n) return false;
        }
        return n->isEnd;
    }
    
    int main() {
        Node* root = new Node();
        for (string w : {"car", "cat", "cart", "care"}) insert(root, w);
        cout << boolalpha << search(root, "cart") << " " << search(root, "ca") << "\n";  // true false
    }

    Where are tries used?

    • Autocomplete and search suggestions as you type.
    • Spell checkers and word games (Boggle, Scrabble solvers).
    • IP routing: routers find the longest matching address prefix with a binary trie.
    • Dictionaries for T9 / phone keyboards.
    • Interview problems: “word search II”, “longest common prefix”, “replace words”.

    Common mistakes

    • Forgetting the isEnd flag, so prefixes are reported as words.
    • Using a fixed 26-slot array for non-lowercase input (capitals, digits, Unicode) — use a map instead.
    • Ignoring memory: a trie of many unrelated long words can be larger than a hash set.

    Complexity at a glance

    Case / operationTimeWhy
    Insert a word of length LO(L)One step per letter — independent of how many words are stored.
    Search a word of length LO(L)Same walk as insert.
    Prefix search (autocomplete)O(L + k)Walk the prefix, then collect k results.
    Extra spaceO(total letters × alphabet)

    Quick check

    Test yourself — pick an answer to see if you got it.

    1. What does a green (end-of-word) node mean?

    2. How long does it take to search for a 5-letter word in a trie containing 1 million words?

    3. The words "car", "cart" and "care" are inserted. How many nodes do they use (not counting the root)?

    4. Which feature is a trie especially good at?

    Saved only in this browser — no account needed.
    Spotted a mistake or a bug in the 3D model?

    Report a mistake

    in Trie (Prefix Tree). Thank you — every report makes the lesson better for the next reader.

    We'll also include a link to the step of the 3D model you're on and your browser type, so we can reproduce it.