{
    "slug": "trie_data_structure",
    "term": "Trie (Prefix Tree)",
    "category": "data_structures",
    "difficulty": "intermediate",
    "short": "A tree where each node represents a character — paths from root to leaf spell out keys, enabling O(m) lookup, prefix search, and autocomplete where m is key length, independent of dataset size.",
    "long": "A trie stores strings by decomposing them character by character. Each edge represents one character; a path from the root to a marked node spells a complete key. Lookup, insert, and prefix search all run in O(m) time where m is the string length — completely independent of how many keys are stored. This makes tries superior to hash tables for prefix queries (autocomplete, IP routing, spell checking) where a hash table would require scanning all keys. A standard trie uses O(n×alphabet_size) memory which is often wasteful; compressed tries (Patricia/radix trees) merge single-child nodes to reduce memory. PHP's built-in data structures do not include a trie, but one can be implemented with nested arrays or SplFixedArray for the character map. Redis Sorted Sets and full-text search engines use trie variants internally for prefix lookups.",
    "aliases": [],
    "tags": [
        "data-structures",
        "search",
        "autocomplete",
        "strings",
        "algorithms"
    ],
    "misconception": "Tries are not always faster than hash tables — for exact-match lookups a hash table's O(1) average beats a trie's O(m). Tries win only when prefix queries or sorted key iteration are required.",
    "why_it_matters": "Autocomplete, IP routing tables, and spell checkers rely on prefix queries that hash tables and binary trees cannot serve efficiently at scale — a trie answers \"all words starting with ph\" in O(prefix_length) time.",
    "common_mistakes": [
        "Using a trie for exact-match-only lookups where a hash map is simpler and faster on average.",
        "Naively implementing a trie with 26-slot arrays at every node — sparse character sets waste memory; use a map/dictionary per node instead.",
        "Forgetting to mark end-of-word nodes — without an is_end flag, 'car' and 'card' both appear as stored keys when only 'card' was inserted."
    ],
    "when_to_use": [
        "Use a trie for autocomplete or typeahead — retrieving all keys with a given prefix is a single traversal to the prefix node.",
        "Use it for IP routing table lookups (longest prefix match) where binary search on sorted CIDRs is too slow.",
        "Use a compressed trie (radix tree) when memory is a concern but prefix search semantics are still needed."
    ],
    "avoid_when": [
        "Avoid tries for pure exact-match lookups — a hash table has lower overhead and simpler implementation.",
        "Do not use a naive trie for Unicode strings without normalising to a fixed-width encoding — variable-width characters make per-character edge logic error-prone."
    ],
    "related": [
        "hash_table",
        "binary_tree",
        "typeahead_autocomplete"
    ],
    "prerequisites": [],
    "refs": [
        "https://en.wikipedia.org/wiki/Trie"
    ],
    "bad_code": "// Linear scan for prefix search — O(n) per query:\nfunction autocomplete(array $words, string $prefix): array {\n    return array_filter($words, fn($w) => str_starts_with($w, $prefix));\n    // 100k words × every keystroke = very slow\n}",
    "good_code": "// Trie insert + prefix search — O(prefix_len) to find node, O(results) to collect:\nfunction trieInsert(array &$root, string $word): void {\n    $node = &$root;\n    foreach (str_split($word) as $ch) {\n        $node = &$node[$ch];\n    }\n    $node['*'] = true; // end-of-word marker\n}\n\nfunction trieSearch(array $root, string $prefix): array {\n    $node = $root;\n    foreach (str_split($prefix) as $ch) {\n        if (!isset($node[$ch])) return [];\n        $node = $node[$ch];\n    }\n    return collectWords($node, $prefix);\n}",
    "example_note": "The bad example scans all 100k words on every keystroke — O(n) per character typed. The trie insert is O(word_length) once; prefix search traverses only the prefix path then collects matching subtree keys.",
    "created": "2026-03-31",
    "updated": "2026-03-31",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/trie_data_structure",
        "html_url": "https://codeclaritylab.com/glossary/trie_data_structure",
        "json_url": "https://codeclaritylab.com/glossary/trie_data_structure.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Trie (Prefix Tree)](https://codeclaritylab.com/glossary/trie_data_structure) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/trie_data_structure"
            }
        }
    }
}