package main
import (
"fmt"
)
// TrieNode represents each node in the trie
// It holds children nodes and a flag if it's end of a word
type TrieNode struct {
children map[rune]*TrieNode
isEnd bool
}
// Trie structure with root node
type Trie struct {
root *TrieNode
}
// NewTrieNode creates a new TrieNode
func NewTrieNode() *TrieNode {
return &TrieNode{children: make(map[rune]*TrieNode)}
}
// NewTrie creates a new Trie with root node
func NewTrie() *Trie {
return &Trie{root: NewTrieNode()}
}
// Insert adds a word into 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 returns the node where prefix ends or nil if not found
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 below given 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
}
}
// StartsWith returns all words starting with given prefix
func (t *Trie) StartsWith(prefix string) []string {
results := []string{}
node := t.searchNode(prefix) // find node for prefix
if node == nil {
return results // no words with prefix
}
t.collectWords(node, prefix, &results) // collect all words below
return results
}
func main() {
trie := NewTrie()
words := []string{"tree", "trie", "algo", "algo"}
for _, w := range words {
trie.Insert(w)
}
prefix := "tr"
results := trie.StartsWith(prefix)
fmt.Printf("Words with prefix '%s': %s\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 of word reached
t.collectWords(child, prefix+string(ch), results) // explore children
recursively collect all words below current node
Words with prefix 'tr': [tree trie]