classTrieNode{ publicboolean isWord; public TrieNode[] next; privatefinalint charCount = 26; publicTrieNode(){ next = new TrieNode[charCount]; } }
publicclassTrie{ private TrieNode root;
/** Initialize your data structure here. */ publicTrie(){ root = new TrieNode(); } /** Inserts a word into the trie. */ publicvoidinsert(String word){ if(word == null || word.length() == 0) return; TrieNode node = root; int d = 0; // depth/distance while(d < word.length()) { char c = word.charAt(d); if(node.next[c - 'a'] == null) node.next[c - 'a'] = new TrieNode(); node = node.next[c - 'a']; d++; } node.isWord = true; } /** Returns if the word is in the trie. */ publicbooleansearch(String word){ if(word == null || word.length() == 0) returnfalse; TrieNode node = root; int d = 0; while(d < word.length()) { char c = word.charAt(d); if(node.next[c - 'a'] == null) // did not find char within word returnfalse; node = node.next[c - 'a']; d++; } return node.isWord; } /** Returns if there is any word in the trie that starts with the given prefix. */ publicbooleanstartsWith(String prefix){ if(prefix == null || prefix.length() == 0) returnfalse; TrieNode node = root; int d = 0; while(d < prefix.length()) { char c = prefix.charAt(d); if(node.next[c - 'a'] == null) // did not find char within prefix returnfalse; node = node.next[c - 'a']; d++; } returntrue; } }
/** * Your Trie object will be instantiated and called as such: * Trie obj = new Trie(); * obj.insert(word); * boolean param_2 = obj.search(word); * boolean param_3 = obj.startsWith(prefix); */
type Trie struct { childMap map[byte]*Trie isWord bool }
/** Initialize your data structure here. */ funcConstructor()Trie { return Trie{ childMap: make(map[byte]*Trie), isWord: false, } }
/** Inserts a word into the trie. */ func(this *Trie)Insert(word string) { iflen(word) == 0 { return } currentNode := this for i := 0; i < len(word); i++ { nextNode, exist := currentNode.childMap[word[i]] if exist { currentNode = nextNode } else { newNode := Constructor() currentNode.childMap[word[i]] = &newNode currentNode = &newNode } } currentNode.isWord = true }
/** Returns if the word is in the trie. */ func(this *Trie)Search(word string)bool { iflen(word) == 0 { returnfalse } var current, next *Trie = this, nil ok := false for i := 0; i < len(word); i++ { if next, ok = current.childMap[word[i]]; !ok { returnfalse } current = next } return next.isWord }
/** Returns if there is any word in the trie that starts with the given prefix. */ func(this *Trie)StartsWith(prefix string)bool { iflen(prefix) == 0 { returnfalse } var current, next *Trie = this, nil ok := false for i := 0; i < len(prefix); i++ { if next, ok = current.childMap[prefix[i]]; !ok { returnfalse } current = next } returntrue }
/** * Your Trie object will be instantiated and called as such: * obj := Constructor(); * obj.Insert(word); * param_2 := obj.Search(word); * param_3 := obj.StartsWith(prefix); */
可以阅读一下 redisearch 的 trie tree 的代码,感受一下前缀树在搜索引擎中的实际应用,C 语言的代码,非常简洁优雅。