Go语言实现前缀树 | 青训营笔记

94 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第4篇笔记

什么是前缀树?

前缀树是N叉树的一种特殊形式。通常来说,一个前缀树是用来存储字符串的。前缀树的每一个节点代表一个字符串(前缀)。每一个节点会有多个子节点,通往不同子节点的路径上有着不同的字符。子节点代表的字符串是由节点本身的原始字符串,以及通往该子节点路径上所有的字符组成的。

举例

image.png

在上图示例中,我们在节点中标记的值是该节点对应表示的字符串。例如,我们从根节点开始,选择第二条路径 ‘b’,然后选择它的第一个子节点 ‘a’,接下来继续选择子节点 ‘d’,我们最终会到达叶节点 “bad”。节点的值是由从根节点开始,与其经过的路径中的字符按顺序形成的。

值得注意的是,根节点表示空字符串。

前缀树的一个重要的特性是,节点所有的后代都与该节点相关的字符串有着共同的前缀。这就是前缀树名称的由来。

我们再来看这个例子。例如,以节点 “b” 为根的子树中的节点表示的字符串,都具有共同的前缀 “b”。反之亦然,具有公共前缀 “b” 的字符串,全部位于以 “b” 为根的子树中,并且具有不同前缀的字符串来自不同的分支。

代码实现:

type Trie struct {
   next  []*Trie
   isEnd bool
}

func Constructor() Trie {
   root := Trie{
      next:  make([]*Trie, 26),
      isEnd: false,
   }
   return root
}

func (this *Trie) Insert(word string) {
   node := this
   for _, c := range word {
      idx := c - 'a'
      if node.next[idx] == nil {
         trie := Constructor()
         node.next[idx] = &trie
      }
      node = node.next[idx]
   }
   node.isEnd = true
}

func (this *Trie) Search(word string) bool {
   node := this
   for _, c := range word {
      idx := c - 'a'
      if node.next[idx] == nil {
         return false
      }
      node = node.next[idx]
   }
   return node.isEnd
}

func (this *Trie) StartsWith(prefix string) bool {
   node := this
   for _, c := range prefix {
      idx := c - 'a'
      if node.next[idx] == nil {
         return false
      }
      node = node.next[idx]
   }
   return true
}