package main
import "fmt"
// TrieNode represents each node in the trie
type TrieNode struct {
children map[rune]*TrieNode
isEnd bool
}
// Trie structure with root node
type Trie struct {
root *TrieNode
}
// NewTrieNode creates a new trie node
func NewTrieNode() *TrieNode {
return &TrieNode{children: make(map[rune]*TrieNode)}
}
// NewTrie creates a new trie
func NewTrie() *Trie {
return &Trie{root: NewTrieNode()}
}
// Insert adds a word to the trie
func (t *Trie) Insert(word string) {
curr := t.root
for _, ch := range word {
if curr.children[ch] == nil {
curr.children[ch] = NewTrieNode() // create node if missing
}
curr = curr.children[ch] // move to child node
}
curr.isEnd = true // mark end of word
}
// searchNode finds the node matching prefix
func (t *Trie) searchNode(prefix string) *TrieNode {
curr := t.root
for _, ch := range prefix {
if curr.children[ch] == nil {
return nil // prefix not found
}
curr = curr.children[ch] // move to next node
}
return curr
}
// collectWords recursively collects all words from node
func (t *Trie) collectWords(node *TrieNode, prefix string, results *[]string) {
if node.isEnd {
*results = append(*results, prefix) // found a word
}
for ch, child := range node.children {
t.collectWords(child, prefix+string(ch), results) // explore children
}
}
// Autocomplete returns all words starting with prefix
func (t *Trie) Autocomplete(prefix string) []string {
results := []string{}
node := t.searchNode(prefix) // find prefix node
if node == nil {
return results // no words found
}
t.collectWords(node, prefix, &results) // collect all words
return results
}
func main() {
trie := NewTrie()
words := []string{"cat", "car", "cars", "dog"}
for _, w := range words {
trie.Insert(w) // insert each word
}
prefix := "ca"
results := trie.Autocomplete(prefix) // get autocomplete
fmt.Printf("Autocomplete results for \"%s\": %v\n", prefix, results)
}if curr.children[ch] == nil {
curr.children[ch] = NewTrieNode() // create node if missing
}
create new node if letter path does not exist
curr = curr.children[ch] // move to child node
advance current node to next letter node
curr.isEnd = true // mark end of word
mark node as end of a valid word
if curr.children[ch] == nil {
return nil // prefix not found
}
stop search if prefix letter missing
if node.isEnd {
*results = append(*results, prefix) // found a word
}
add word to results when end node reached
t.collectWords(child, prefix+string(ch), results) // explore children
recursively explore all child nodes to find words
Autocomplete results for "ca": [cat car cars]