Trie (Prefix Tree) Veri Yapısı
Trie, prefix tree olarak da bilinen, string verilerini verimli bir şekilde saklamak ve araştırmak için kullanılan ağaç benzeri bir veri yapısıdır. Her düğüm bir karakteri temsil eder ve kök düğümden yapraklara doğru giden yol bir string oluşturur.
Avantajlar
- String arama işlemleri çok hızlıdır (O(m) - string uzunluğu)
- Prefix tabanlı aramalar için idealdir (autocomplete)
- Longest common prefix bulma işlemleri etkilidir
- String sorting işlemlerinde kullanılabilir
- Dictionary ve spell checker uygulamaları için mükemmeldir
Dezavantajlar
- Yüksek bellek tüketimi (her düğüm için alphabet boyutu kadar pointer)
- Cache locality performance düşük olabilir
- Küçük dataset'lerde hash table'dan yavaş olabilir
- Implementation karmaşıklığı hash table'dan fazladır
İnteraktif Trie Görselleştirme
Aşağıdaki görselleştirici ile Trie veri yapısını keşfedebilirsiniz. Kelimeler ekleyin, silin ve prefix tabanlı arama işlemlerini test edin.
Trie Düğüm Renkleri
Genel Bilgiler
• Yeşil düğümler tamamlanmış kelimeleri temsil eder
• Parantez içindeki sayı kelimenin kaç kez eklendiğini gösterir
• Mavi etiketler tamamlanmış kelimeyi gösterir
Trie (Prefix Tree)
Zaman Karmaşıklığı:
- Ekleme: O(m) - m kelime uzunluğu
- Arama: O(m)
- Prefix arama: O(p + k) - p prefix uzunluğu, k sonuç sayısı
Alan Karmaşıklığı: O(ALPHABET_SIZE * N * M)
Kullanım Alanları: Otomatik tamamlama, yazım kontrolü, IP routing
Segment Tree
Zaman Karmaşıklığı:
- İnşa etme: O(n)
- Aralık sorgusu: O(log n)
- Güncelleme: O(log n)
Alan Karmaşıklığı: O(n)
Kullanım Alanları: Aralık toplamı, min/max sorguları, lazy propagation
Trie Oluşturma Demo
Virgülle ayrılmış kelimeler girerek Trie oluşturun
Prefix Arama Demo
Belirli prefix ile başlayan kelimeleri bulun
JavaScript Implementasyonu
Trie veri yapısının tam JavaScript implementasyonu. Autocomplete, prefix arama ve istatistik hesaplama özellikleri içerir.
1// Trie (Prefix Tree) JavaScript implementasyonu2class TrieNode {3 constructor() {4 // Her düğüm için karakter-düğüm eşlemesi5 this.children = new Map();6 // Bu düğümde bir kelime bitip bitmediğini belirten flag7 this.isEndOfWord = false;8 // Opsiyonel: kelimenin kendisini saklamak için9 this.value = null;10 // Opsiyonel: kelime sayısını takip etmek için11 this.count = 0;12 }13}1415class Trie {16 constructor() {17 // Kök düğüm - boş karakter temsil eder18 this.root = new TrieNode();19 // Toplam benzersiz kelime sayısı20 this.wordCount = 0;21 }2223 // Yeni kelime ekleme işlemi - O(m) zaman karmaşıklığı24 insert(word) {25 if (!word || word.length === 0) return;2627 let currentNode = this.root;28 const normalizedWord = word.toLowerCase();2930 // Her karakter için düğüm oluştur veya mevcut düğüme git31 for (const char of normalizedWord) {32 if (!currentNode.children.has(char)) {33 currentNode.children.set(char, new TrieNode());34 }35 currentNode = currentNode.children.get(char);36 }3738 // Kelime sonu işaretleme ve sayaç güncelleme39 if (!currentNode.isEndOfWord) {40 this.wordCount++;41 }42 currentNode.isEndOfWord = true;43 currentNode.value = word;44 currentNode.count = (currentNode.count || 0) + 1;45 }4647 // Kelime arama işlemi - O(m) zaman karmaşıklığı48 search(word) {49 if (!word || word.length === 0) return false;5051 const node = this.findNode(word.toLowerCase());52 return node !== null && node.isEndOfWord;53 }5455 // Prefix varlığı kontrolü - O(m) zaman karmaşıklığı56 startsWith(prefix) {57 if (!prefix || prefix.length === 0) return true;5859 return this.findNode(prefix.toLowerCase()) !== null;60 }6162 // Belirli prefix ile başlayan tüm kelimeleri bulma63 getWordsWithPrefix(prefix) {64 const words = [];65 const prefixNode = this.findNode(prefix.toLowerCase());6667 if (prefixNode) {68 this.collectWords(prefixNode, prefix.toLowerCase(), words);69 }7071 return words;72 }7374 // Autocomplete öneriler - en çok kullanılan kelimeler öncelikli75 getAutocompleteSuggestions(prefix, maxSuggestions = 10) {76 const words = this.getWordsWithPrefix(prefix);77 78 // Count'a göre sırala ve en çok kullanılanları döndür79 return words80 .map(word => ({81 word,82 count: this.getWordCount(word)83 }))84 .sort((a, b) => b.count - a.count)85 .slice(0, maxSuggestions)86 .map(item => item.word);87 }8889 // Kelime silme işlemi - O(m) zaman karmaşıklığı90 delete(word) {91 if (!word || word.length === 0) return false;9293 return this.deleteHelper(this.root, word.toLowerCase(), 0);94 }9596 // Trie'daki tüm kelimeleri alma97 getAllWords() {98 const words = [];99 this.collectWords(this.root, '', words);100 return words;101 }102103 // Toplam benzersiz kelime sayısını döndürme104 getWordCount() {105 return this.wordCount;106 }107108 // Belirli bir kelimenin kaç kez eklendiğini öğrenme109 getWordFrequency(word) {110 const node = this.findNode(word.toLowerCase());111 return node && node.isEndOfWord ? node.count : 0;112 }113114 // En uzun ortak prefix bulma115 getLongestCommonPrefix() {116 let current = this.root;117 let prefix = '';118119 // Tek bir çocuk varsa ve kelime sonu değilse devam et120 while (current.children.size === 1 && !current.isEndOfWord) {121 const char = Array.from(current.children.keys())[0];122 prefix += char;123 current = current.children.get(char);124 }125126 return prefix;127 }128129 // Trie'ın istatistiklerini döndürme130 getStatistics() {131 let nodeCount = 0;132 let maxDepth = 0;133 let totalPaths = 0;134135 const traverse = (node, depth) => {136 nodeCount++;137 maxDepth = Math.max(maxDepth, depth);138 139 if (node.isEndOfWord) {140 totalPaths++;141 }142143 for (const child of node.children.values()) {144 traverse(child, depth + 1);145 }146 };147148 traverse(this.root, 0);149150 return {151 nodeCount,152 maxDepth,153 totalWords: this.wordCount,154 totalPaths,155 avgDepth: totalPaths > 0 ? maxDepth / totalPaths : 0156 };157 }158159 // Yardımcı metod: belirli kelime/prefix için düğüm bulma160 findNode(word) {161 let currentNode = this.root;162163 for (const char of word) {164 if (!currentNode.children.has(char)) {165 return null;166 }167 currentNode = currentNode.children.get(char);168 }169170 return currentNode;171 }172173 // Belirli düğümden başlayarak tüm kelimeleri toplama174 collectWords(node, prefix, words) {175 if (node.isEndOfWord && node.value) {176 words.push(node.value);177 }178179 // Tüm çocukları dolaş ve kelimeleri topla180 node.children.forEach((childNode, char) => {181 this.collectWords(childNode, prefix + char, words);182 });183 }184185 // Rekursif silme yardımcı metodu186 deleteHelper(node, word, index) {187 if (index === word.length) {188 // Kelimenin sonuna ulaştık189 if (!node.isEndOfWord) {190 return false; // Kelime mevcut değil191 }192193 node.isEndOfWord = false;194 node.value = null;195 this.wordCount--;196197 // Düğümün çocuğu yoksa silinebilir198 return node.children.size === 0;199 }200201 const char = word[index];202 const childNode = node.children.get(char);203204 if (!childNode) {205 return false; // Kelime mevcut değil206 }207208 const shouldDeleteChild = this.deleteHelper(childNode, word, index + 1);209210 // Çocuk düğümü silinmeli mi kontrol et211 if (shouldDeleteChild) {212 node.children.delete(char);213 // Mevcut düğüm de silinebilir mi kontrol et214 return !node.isEndOfWord && node.children.size === 0;215 }216217 return false;218 }219220 // Belirli kelimenin count değerini döndürme221 getWordCount(word) {222 const node = this.findNode(word.toLowerCase());223 return node && node.isEndOfWord ? node.count : 0;224 }225}226227// Kullanım örneği ve test228const trie = new Trie();229230// Kelime ekleme231const words = ['cat', 'cats', 'car', 'card', 'care', 'careful', 'cars', 'carry'];232words.forEach(word => trie.insert(word));233234// Arama işlemleri235console.log('Search "car":', trie.search('car')); // true236console.log('Search "care":', trie.search('care')); // true237console.log('Search "caring":', trie.search('caring')); // false238239// Prefix kontrolü240console.log('StartsWith "car":', trie.startsWith('car')); // true241console.log('StartsWith "dog":', trie.startsWith('dog')); // false242243// Autocomplete244console.log('Words with prefix "car":', trie.getWordsWithPrefix('car'));245// ['car', 'card', 'care', 'careful', 'cars', 'carry']246247// İstatistikler248console.log('Trie statistics:', trie.getStatistics());
Trie vs Hash Table Performans Karşılaştırması
Trie Advantages
Hash Table Advantages
Trie Optimizasyon Teknikleri
Bellek Optimizasyonu
- • Compressed Trie: Tek çocuklu düğümleri birleştir
- • Radix Tree: Edge compression uygula
- • Patricia Tree: Binary radix tree kullan
- • Ternary Search Tree: 3-way branching
Performans Optimizasyonu
- • Array-based Storage: Map yerine array kullan
- • Cache-friendly Layout: Düğümleri sıralı yerleştir
- • Lazy Evaluation: Gereksiz computation'ları ertele
- • Parallel Operations: Thread-safe implementasyon
Gerçek Dünya Uygulamaları ve Örnekler
Web ve Mobil Uygulamalar
- • Google Search: Autocomplete suggestions
- • IDE'ler: Code completion ve IntelliSense
- • Sosyal Medya: Hashtag ve mention suggestions
- • E-ticaret: Product search autocomplete
Sistem ve Network Uygulamaları
- • Router Tables: IP address longest prefix matching
- • DNS Resolution: Domain name lookup optimization
- • Compiler Design: Keyword recognition ve lexical analysis
- • Spell Checkers: Dictionary lookup ve correction
Trie Variations ve Alternatif Implementasyonlar
Compressed Trie (Radix Tree)
Tek çocuklu düğümleri birleştirerek bellek kullanımını optimize eder. Suffix tree'lerin temelini oluşturur.
Ternary Search Tree
Binary search tree'nin string'ler için adaptasyonu. Daha az bellek kullanır ama biraz daha yavaştır.
Suffix Tree
Bir string'in tüm suffix'lerini içeren compressed trie. Pattern matching ve string analysis için kullanılır.