--- id: cs-tries-trees title: Tries / Trees — Prefix / Autocomplete / Routing category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [cs, tree, trie, vibe-coding] tech_stack: { language: "TS", applicable_to: ["Backend", "Frontend"] } applied_in: [] aliases: [Trie, prefix tree, radix tree, ART, autocomplete, route matching, suffix tree] --- # Tries / Trees > Prefix-based 자료구조. **Autocomplete, route match, IP routing, dictionary**. Trie / Radix / ART (Adaptive Radix Tree). String key 가 자연. ## 📖 핵심 개념 - Trie: 매 char 가 node. - Radix: 같은 path 압축. - ART: cache-friendly, modern. - Suffix tree: 모든 suffix 의 trie. ## 💻 코드 패턴 ### Basic Trie ```ts class TrieNode { children = new Map(); isEnd = false; } class Trie { root = new TrieNode(); insert(word: string) { let node = this.root; for (const ch of word) { if (!node.children.has(ch)) { node.children.set(ch, new TrieNode()); } node = node.children.get(ch)!; } node.isEnd = true; } search(word: string): boolean { const node = this.findNode(word); return node?.isEnd ?? false; } startsWith(prefix: string): boolean { return this.findNode(prefix) !== null; } private findNode(s: string): TrieNode | null { let node = this.root; for (const ch of s) { const next = node.children.get(ch); if (!next) return null; node = next; } return node; } } ``` ### Autocomplete ```ts class AutocompleteTrie { // ... 위 + suggestions(prefix: string, max = 10): string[] { const node = this.findNode(prefix); if (!node) return []; const result: string[] = []; this.collect(node, prefix, result, max); return result; } private collect(node: TrieNode, current: string, result: string[], max: number) { if (result.length >= max) return; if (node.isEnd) result.push(current); for (const [ch, child] of node.children) { this.collect(child, current + ch, result, max); } } } const trie = new AutocompleteTrie(); ['apple', 'app', 'application', 'apply'].forEach(w => trie.insert(w)); trie.suggestions('app'); // ['app', 'apple', 'application', 'apply'] ``` ### Frequency-based autocomplete ```ts class FrequencyTrie { root = new TrieNode(); insert(word: string, freq: number = 1) { let node = this.root; for (const ch of word) { if (!node.children.has(ch)) { node.children.set(ch, new TrieNode()); } node = node.children.get(ch)!; } node.frequency = (node.frequency ?? 0) + freq; node.word = word; } topSuggestions(prefix: string, k = 5): string[] { const node = this.findNode(prefix); if (!node) return []; // Heap 또는 sort const all: { word: string; freq: number }[] = []; this.collectAll(node, all); return all .sort((a, b) => b.freq - a.freq) .slice(0, k) .map(x => x.word); } } ``` → Search query autocomplete. ### Radix tree (compressed trie) ```ts // "apple", "app", "apply" // Trie: a→p→p→l→e (end), p (end), p→l→y (end) // Radix: "app" (end) → "le" (end), "ly" (end) // ↳ "ication" (end) class RadixNode { children = new Map(); // edge label → node isEnd = false; value?: any; } class RadixTree { root = new RadixNode(); insert(key: string, value: any) { // Common prefix 찾기 → split or extend // ... 복잡 implementation } } ``` → Memory 절약. URL routing 자주. ### URL routing (radix tree) ``` GET /users/:id GET /users/:id/posts GET /posts/:id POST /posts Tree: / ├── users/ │ └── :id/ │ └── posts/ └── posts/ └── :id (또는 default) ``` ```ts // find-my-way (Fastify 사용) import findMyWay from 'find-my-way'; const router = findMyWay(); router.on('GET', '/users/:id', (req, res, params) => { res.end(`User ${params.id}`); }); const match = router.find('GET', '/users/123'); // { handler, params: { id: '123' } } ``` → Express / Fastify / Hono 의 router internals. ### IP routing (longest prefix match) ``` 192.168.1.0/24 → router A 192.168.0.0/16 → router B 0.0.0.0/0 → router C (default) → Trie of bits. ``` ```ts class IPTrie { // Each bit (0 / 1) = child // Leaf = next-hop } ``` → Linux kernel routing. ### Suffix tree ``` "banana" 의 모든 suffix: - banana - anana - nana - ana - na - a Suffix tree = 이 suffix 모두 의 trie (compressed). ``` ```ts // Substring search 빠름 (O(m), m = pattern length). // Build = O(n). // Use case: bioinformatics, text search. ``` → Ukkonen's algorithm. ### Aho-Corasick (multi-pattern) ```ts // 여러 pattern 을 한 번에 search. // Trie + failure link. const ac = new AhoCorasick(); ac.add('cat'); ac.add('dog'); ac.add('cattle'); ac.build(); const matches = ac.search('thecattleshookhead'); // [{ pattern: 'cat', start: 3 }, { pattern: 'cattle', start: 3 }] ``` → Spam filter, DNA search, IDS. ### Prefix sum (different from trie) ```ts // "ABC" → counts at each position const prefix: number[] = [0]; for (const ch of str) prefix.push(prefix[prefix.length - 1] + (ch === 'a' ? 1 : 0)); // Range query: prefix[r] - prefix[l] ``` ### Segment tree ```ts // Range query / range update. // 매 node 가 range 의 sum / min / max. class SegmentTree { tree: number[]; n: number; constructor(arr: number[]) { this.n = arr.length; this.tree = new Array(4 * this.n); this.build(arr, 0, 0, this.n - 1); } query(l: number, r: number): number { return this.queryHelper(0, 0, this.n - 1, l, r); } update(idx: number, val: number) { this.updateHelper(0, 0, this.n - 1, idx, val); } } ``` → Range sum / max / min 자주. ### Fenwick tree (BIT) ```ts // Range sum + point update. // Segment tree 보다 작음. class BIT { tree: number[]; constructor(n: number) { this.tree = new Array(n + 1).fill(0); } update(i: number, delta: number) { for (; i < this.tree.length; i += i & -i) this.tree[i] += delta; } query(i: number): number { let sum = 0; for (; i > 0; i -= i & -i) sum += this.tree[i]; return sum; } } ``` → Inversion count, range sum. ### Splay tree / Red-black tree / AVL ``` Self-balancing BST. - Splay: recently used = root (cache friendly) - Red-black: balance via color - AVL: balance via height Used in: - TreeMap / TreeSet (Java) - std::map (C++) - Linux kernel (Red-black for processes) ``` ### B-tree (DB index) ``` [[CS_BTree_LSM_Storage]]: 매 node 가 multiple key (10-100s). Disk-friendly. Postgres / MySQL InnoDB. ``` ### Patricia trie (compressed binary) ``` Bits 의 radix tree. - IP routing - Bitcoin merkle patricia (Ethereum state) ``` ### MerkleTrie (Ethereum) ``` Hash 가 children 의 hash: - Tamper detection - Light client (proof) ``` ### k-d tree (k-dimensional) ``` N-dim points 의 BST. Use: - Nearest neighbor search - Range query - 2D / 3D point cloud ``` ```ts class KDTree { // Each node split by 1 dim. // Alternate dimensions. } // 또는 외부 lib import { kdTree } from 'kd-tree-javascript'; const tree = new kdTree(points, distance, ['x', 'y', 'z']); const nearest = tree.nearest({ x: 0, y: 0, z: 0 }, 5); // top 5 ``` ### Quadtree (2D 공간) ```ts // Game collision, geo search. // 매 node = 4 quadrants. class Quadtree { bounds: Rect; points: Point[]; children: Quadtree[] = []; insert(p: Point) { if (this.children.length > 0) { const idx = this.getIdx(p); this.children[idx].insert(p); } else { this.points.push(p); if (this.points.length > MAX_POINTS) this.split(); } } } ``` ### Geohash ``` Lat/lon → string prefix. "u4pruyd" — 0.6m precision. Prefix match = nearby: "u4pru" matches all in 5km of 'u4pru' area. → Trie + geo. ``` ```ts import geohash from 'ngeohash'; const hash = geohash.encode(37.5, 127.0, 9); // 9 char ≈ 4.8m const decoded = geohash.decode(hash); // {latitude, longitude} const neighbors = geohash.neighbors(hash); ``` ### Use cases summary ``` Trie: - Autocomplete (search box) - Spell check - IP routing - Dictionary (English words) - 회사 jargon Radix: - URL router (Express, Fastify) - Memory-efficient string key ART: - In-memory DB (Hekaton) - Cache-friendly Suffix tree: - DNA / bioinformatics - Substring search B-tree: - DB index (Postgres, MySQL) - File system (ext4) Segment tree / BIT: - Range query - Competitive programming k-d tree / quadtree: - Geo search - Game collision ``` ### Performance ``` Trie operations: - Insert / search: O(L) — L = key length - Memory: O(N × L) — N = key count Radix: - Same as Trie + 작은 메모리 (compression) Hash map (alternative): - O(1) — but no prefix - Use trie when prefix matters ``` ### Trie vs hash map ``` Trie: + Prefix query (autocomplete) + Sorted order + Lex traversal - 큰 메모리 (per char) Hash map: + O(1) lookup + 작은 메모리 - No prefix ``` ### Production library ``` - find-my-way: Fastify router (radix) - ART: Adaptive Radix Tree (C / Rust) - 자체: TS 직접 구현 OK ``` ### When NOT to use trie ``` - Prefix 안 필요 (Hash map) - 큰 string + 적은 query (Bloom filter) - Memory critical (hash + Bloom) ``` ## 🤔 의사결정 기준 | 사용 | 추천 | |---|---| | Autocomplete | Trie / Radix | | URL routing | Radix tree | | IP routing | Patricia / Radix bit | | Substring search 큰 | Suffix tree / Aho-Corasick | | Range query | Segment / BIT | | Geo search | Quadtree / k-d tree / Geohash | | In-memory DB | ART | ## ❌ 안티패턴 - **모든 곳 Trie**: hash map 충분 자주. - **Trie 의 메모리 무 측정**: 큰 dataset = OOM. - **Recursion depth (deep trie)**: stack overflow. iterative. - **String key 만 가정**: binary trie 도 가능. - **Suffix tree O(n²) build**: O(n) Ukkonen's. ## 🤖 LLM 활용 힌트 - Autocomplete = Trie 의 자연 use case. - URL router 안 Radix tree. - Geo = Geohash + Quadtree. - DB = B-tree (다른 문서). ## 🔗 관련 문서 - [[CS_BTree_LSM_Storage]] - [[CS_Big_O_Practical]] - [[DB_Full_Text_Search]]