就相当于多叉树嘛。26个字母。根节点我们默认空,然后下面分出来26个子节点。。
当插入单词的时候,两种情况:1.字母存在,那么node = node.next[字母] ,但是我们并不在意这个节点存的啥,只要它存在就行。 2.字母不存在,那么就给他赋值一个结构体。 当最后全部出入完毕的时候给node.isend赋值true
查询的时候也是两种情况:1.字母不存在就是node.next【字母】==nil,直接可以返回nil 2.存在不为空的时候,遍历下一个执指针走到node = node.next[字母]
在真正查询单词在不在的时候,要注意isend条件,只有上一个函数返回不空并且end为true的时候,单词才真的在前缀树里。
type Trie struct {
//相当于下边练了26个分支
next [26]*Trie
isEnd bool
}
func Constructor6() Trie {
return Trie{}
}
//我们从字典树的根开始,插入字符串。对于当前字符对应的子节点,有两种情况:
//
//子节点存在。沿着指针移动到子节点,继续处理下一个字符。
//子节点不存在。创建一个新的子节点,记录在 \textit{children}children 数组的对应位置上,然后沿着指针移动到子节点,继续搜索下一个字符。
//
func (this *Trie) Insert(word string) {
node := this
for _,ch :=range word{
ch -= 'a'
if node.next[ch] == nil{
node.next[ch] = &Trie{}
}
node = node.next[ch]
}
node.isEnd = true
}
func (this *Trie) Search(word string) bool {
node := this.SearchPrefix(word)
return node != nil && node.isEnd
}
func (this *Trie) StartsWith(prefix string) bool {
return this.SearchPrefix(prefix) != nil
}
//我们从字典树的根开始,查找前缀。对于当前字符对应的子节点,有两种情况:
//
//子节点存在。沿着指针移动到子节点,继续搜索下一个字符。
//子节点不存在。说明字典树中不包含该前缀,返回空指针。
//若搜索到了前缀的末尾,就说明字典树中存在该前缀。
//此外,若前缀末尾对应节点的 isEnd 为真,则说明字典树中存在该字符串。
func (this *Trie) SearchPrefix(prefix string) *Trie {
node := this
for _, ch := range prefix {
ch -= 'a'
if node.next[ch] == nil {
return nil
}
node = node.next[ch]
}
return node
}