"cat", "car", and "dog" in order?use std::collections::BTreeMap; #[derive(Debug)] struct TrieNode { children: BTreeMap<char, TrieNode>, is_end_of_word: bool, } impl TrieNode { fn new() -> Self { TrieNode { children: BTreeMap::new(), is_end_of_word: false, } } fn insert(&mut self, word: &str) { let mut current = self; for ch in word.chars() { current = current.children.entry(ch).or_insert(TrieNode::new()); } current.is_end_of_word = true; } fn print(&self, prefix: String) { if self.is_end_of_word { println!("{} (end)", prefix); } for (ch, node) in &self.children { node.print(format!("{}{}", prefix, ch)); } } } fn main() { let mut root = TrieNode::new(); root.insert("cat"); root.insert("car"); root.insert("dog"); root.print(String::new()); }
The print function prints words in alphabetical order because BTreeMap keys are iterated in sorted order. The inserted words are "cat", "car", and "dog". The print order is car, cat, then dog.
"bat", "bath", and "batman" into an empty Trie, what is the output of printing all words stored in the Trie?use std::collections::BTreeMap; #[derive(Debug)] struct TrieNode { children: BTreeMap<char, TrieNode>, is_end_of_word: bool, } impl TrieNode { fn new() -> Self { TrieNode { children: BTreeMap::new(), is_end_of_word: false, } } fn insert(&mut self, word: &str) { let mut current = self; for ch in word.chars() { current = current.children.entry(ch).or_insert(TrieNode::new()); } current.is_end_of_word = true; } fn print(&self, prefix: String) { if self.is_end_of_word { println!("{} (end)", prefix); } for (ch, node) in &self.children { node.print(format!("{}{}", prefix, ch)); } } } fn main() { let mut root = TrieNode::new(); root.insert("bat"); root.insert("bath"); root.insert("batman"); root.print(String::new()); }
The words share the prefix "bat". The print function prints words in alphabetical order: "bat", "bath", then "batman".
fn insert(&mut self, word: &str) { let mut current = self; for ch in word.chars() { current = current.children.get_mut(&ch).unwrap(); } current.is_end_of_word = true; }
The method uses get_mut(&ch).unwrap(). If the character is not found, get_mut returns None, so unwrap() panics. This leads to a runtime panic when trying to insert a word with unseen characters.
HashMap<char, TrieNode> commonly used to store children in a Trie node instead of a fixed-size array?Using a HashMap allows storing only existing children nodes, which saves memory when the alphabet is large and many nodes have few children. Fixed-size arrays allocate space for all possible characters, wasting memory.
prefix?fn count_words_with_prefix(node: &TrieNode, prefix: &str) -> usize { let mut current = node; for ch in prefix.chars() { match current.children.get(&ch) { Some(next_node) => current = next_node, None => return 0, } } fn count_all_words(node: &TrieNode) -> usize { let mut count = if node.is_end_of_word { 1 } else { 0 }; for child in node.children.values() { count += count_all_words(child); } count } count_all_words(current) }
The code first moves to the node representing the prefix. If prefix not found, returns 0. Then it counts all words under that node recursively, including the prefix node if it is an end of a word.
