Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。小写英文字母或大写英文字母的字典数是一个26叉树。Trie树的根结点是不保存数据的,所有的数据都保存在它的孩子节点中。

    字符串go, golang, php, python, perl,它这棵Trie树可如下图所示构造:
    image.png

    Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。

    基本性质

    • 根节点不包含字符,除根节点外每一个节点都只包含一个字符。
    • 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
    • 每个节点的所有子节点包含的字符都不相同。

    code

    1. package main
    2. import "fmt"
    3. type Trie struct {
    4. // 自身节点 与 若干个子节点
    5. Children map[byte]*Trie
    6. // 标识节点是否是一个单词最后的一个字符
    7. IsWord bool
    8. }
    9. func NewTrie() *Trie {
    10. return &Trie{}
    11. }
    12. func (t *Trie) Add(word string) {
    13. cur := t
    14. // 遍历 word的每一个字符
    15. for _, c := range []byte(word) {
    16. if cur.Children == nil {
    17. cur.Children = make(map[byte]*Trie)
    18. }
    19. // 查找子节点中是否包含当前字符
    20. // 如果不包含, 添加一下
    21. if _, ok := cur.Children[c]; !ok {
    22. cur.Children[c] = NewTrie()
    23. }
    24. // cur 指向子节点
    25. cur = cur.Children[c]
    26. }
    27. // 将最后一个节点字符的 尾设置为 true
    28. cur.IsWord = true
    29. }
    30. func (t *Trie) Search(word string) bool {
    31. cur := t
    32. // 遍历 word的每一个字符
    33. for _, c := range []byte(word) {
    34. // 查找子节点中是否包含当前字符
    35. if _, ok := cur.Children[c]; !ok {
    36. return false
    37. }
    38. // cur 指向下一个子节点
    39. cur = cur.Children[c]
    40. }
    41. // 判断最后一个单词是否是 单词末尾 cur.isWord == true,
    42. // 直接缩写为 cur.isWord
    43. return cur.IsWord
    44. }
    45. func (t *Trie) StartsWith(prefix string) bool {
    46. cur := t
    47. // 遍历 word的每一个字符
    48. for _, c := range []byte(prefix) {
    49. // 查找子节点中是否包含当前字符
    50. if _, ok := cur.Children[c]; !ok {
    51. return false
    52. }
    53. // cur 指向下一个子节点
    54. cur = cur.Children[c]
    55. }
    56. return true
    57. }
    58. func main() {
    59. // 创建字典树
    60. t := NewTrie()
    61. t.Add("door")
    62. // 测试
    63. fmt.Println(t.Search("dog"))
    64. fmt.Println(t.Search("door"))
    65. fmt.Println(t.StartsWith("do"))
    66. }