Tutorials Logic, IN +91 8092939553 info@tutorialslogic.com
FAQs Support
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Interview Questions Website Development
Compiler Tutorials

Trie (Prefix Tree)

What is a Trie?

A Trie (pronounced "try", from retrieval) is a tree-like data structure used to store strings where each node represents a character. It is optimized for prefix-based searches — finding all words with a given prefix is O(prefix length), not O(n × word length).

  • Insert — O(m) where m = word length
  • Search — O(m)
  • Prefix search — O(m)
  • Space — O(ALPHABET_SIZE × m × n) — can be large

Use cases: Autocomplete, spell checkers, IP routing, dictionary implementations, word games.

Trie — Insert, Search, StartsWith, Autocomplete
#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;

struct TrieNode {
    unordered_map<char, TrieNode*> children;
    bool isEnd = false;
};

class Trie {
    TrieNode* root;
public:
    Trie() { root = new TrieNode(); }

    void insert(const string& word) {
        TrieNode* node = root;
        for (char c : word) {
            if (!node->children.count(c))
                node->children[c] = new TrieNode();
            node = node->children[c];
        }
        node->isEnd = true;
    }

    bool search(const string& word) {
        TrieNode* node = root;
        for (char c : word) {
            if (!node->children.count(c)) return false;
            node = node->children[c];
        }
        return node->isEnd;
    }

    bool startsWith(const string& prefix) {
        TrieNode* node = root;
        for (char c : prefix) {
            if (!node->children.count(c)) return false;
            node = node->children[c];
        }
        return true;
    }

    // Autocomplete: find all words with given prefix
    void collectWords(TrieNode* node, string current, vector<string>& results) {
        if (node->isEnd) results.push_back(current);
        for (auto& [c, child] : node->children)
            collectWords(child, current + c, results);
    }

    vector<string> autocomplete(const string& prefix) {
        TrieNode* node = root;
        for (char c : prefix) {
            if (!node->children.count(c)) return {};
            node = node->children[c];
        }
        vector<string> results;
        collectWords(node, prefix, results);
        return results;
    }
};

int main() {
    Trie trie;
    for (const string& w : {"apple","app","application","apply","apt","banana"})
        trie.insert(w);

    cout << boolalpha;
    cout << trie.search("app")    << endl;  // true
    cout << trie.search("ap")     << endl;  // false
    cout << trie.startsWith("app") << endl; // true

    auto words = trie.autocomplete("app");
    cout << "Words with 'app': ";
    for (const string& w : words) cout << w << " ";
    cout << endl;  // app apple application apply
    return 0;
}
import java.util.*;

public class Trie {
    static class TrieNode {
        Map<Character, TrieNode> children = new HashMap<>();
        boolean isEnd = false;
    }

    TrieNode root = new TrieNode();

    void insert(String word) {
        TrieNode node = root;
        for (char c : word.toCharArray()) {
            node.children.putIfAbsent(c, new TrieNode());
            node = node.children.get(c);
        }
        node.isEnd = true;
    }

    boolean search(String word) {
        TrieNode node = root;
        for (char c : word.toCharArray()) {
            if (!node.children.containsKey(c)) return false;
            node = node.children.get(c);
        }
        return node.isEnd;
    }

    boolean startsWith(String prefix) {
        TrieNode node = root;
        for (char c : prefix.toCharArray()) {
            if (!node.children.containsKey(c)) return false;
            node = node.children.get(c);
        }
        return true;
    }

    List<String> autocomplete(String prefix) {
        TrieNode node = root;
        for (char c : prefix.toCharArray()) {
            if (!node.children.containsKey(c)) return new ArrayList<>();
            node = node.children.get(c);
        }
        List<String> results = new ArrayList<>();
        collectWords(node, new StringBuilder(prefix), results);
        return results;
    }

    void collectWords(TrieNode node, StringBuilder current, List<String> results) {
        if (node.isEnd) results.add(current.toString());
        for (Map.Entry<Character, TrieNode> e : node.children.entrySet()) {
            current.append(e.getKey());
            collectWords(e.getValue(), current, results);
            current.deleteCharAt(current.length() - 1);
        }
    }

    public static void main(String[] args) {
        Trie trie = new Trie();
        for (String w : new String[]{"apple","app","application","apply","banana"})
            trie.insert(w);
        System.out.println(trie.search("app"));      // true
        System.out.println(trie.startsWith("app"));  // true
        System.out.println(trie.autocomplete("app")); // [app, apple, application, apply]
    }
}
class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_end = False

class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        node = self.root
        for c in word:
            if c not in node.children:
                node.children[c] = TrieNode()
            node = node.children[c]
        node.is_end = True

    def search(self, word):
        node = self.root
        for c in word:
            if c not in node.children: return False
            node = node.children[c]
        return node.is_end

    def starts_with(self, prefix):
        node = self.root
        for c in prefix:
            if c not in node.children: return False
            node = node.children[c]
        return True

    def autocomplete(self, prefix):
        node = self.root
        for c in prefix:
            if c not in node.children: return []
            node = node.children[c]
        results = []
        self._collect(node, prefix, results)
        return results

    def _collect(self, node, current, results):
        if node.is_end: results.append(current)
        for c, child in node.children.items():
            self._collect(child, current + c, results)

trie = Trie()
for w in ["apple", "app", "application", "apply", "banana"]:
    trie.insert(w)

print(trie.search("app"))        # True
print(trie.search("ap"))         # False
print(trie.starts_with("app"))   # True
print(trie.autocomplete("app"))  # ['app', 'apple', 'application', 'apply']
class TrieNode {
    constructor() { this.children = {}; this.isEnd = false; }
}

class Trie {
    constructor() { this.root = new TrieNode(); }

    insert(word) {
        let node = this.root;
        for (const c of word) {
            if (!node.children[c]) node.children[c] = new TrieNode();
            node = node.children[c];
        }
        node.isEnd = true;
    }

    search(word) {
        let node = this.root;
        for (const c of word) {
            if (!node.children[c]) return false;
            node = node.children[c];
        }
        return node.isEnd;
    }

    startsWith(prefix) {
        let node = this.root;
        for (const c of prefix) {
            if (!node.children[c]) return false;
            node = node.children[c];
        }
        return true;
    }

    autocomplete(prefix) {
        let node = this.root;
        for (const c of prefix) {
            if (!node.children[c]) return [];
            node = node.children[c];
        }
        const results = [];
        this._collect(node, prefix, results);
        return results;
    }

    _collect(node, current, results) {
        if (node.isEnd) results.push(current);
        for (const [c, child] of Object.entries(node.children)) {
            this._collect(child, current + c, results);
        }
    }
}

const trie = new Trie();
["apple","app","application","apply","banana"].forEach(w => trie.insert(w));
console.log(trie.search("app"));        // true
console.log(trie.startsWith("app"));    // true
console.log(trie.autocomplete("app"));  // ['app', 'apple', 'application', 'apply']

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.