使用Golang实现Trie数据结构


Trie 是一种类似树的数据结构,用于存储和搜索动态字符串集合。在处理键共享公共前缀(如字典单词)的数据时非常有用。Trie 与其他检索数据结构的不同之处在于其高效的字符串操作和检索特性。在本文中,我们将学习如何在 Go 编程语言中实现 Trie 数据结构。

解释

Trie,也称为检索树,是一种树形数据结构,通常用于存储和管理字符串集合。它提供对存储字符串的访问。支持各种操作,如插入和删除。这使得它特别适用于涉及搜索和提供建议的任务。

让我们看看 Trie 树

           (root)
          /  |  \
         a   b   b
        /     \   \
       p       a   a
      /|        \   \
     p p         t   l
    /   \         \
   l    le         l
  /
 e
  • 我们在顶部有一个根节点,没有字符。

  • 边连接节点,每条边表示一个字符。

  • 节点可以有多个子节点和字符。

  • 路径 a->p->p->l->e 表示 apple。

  • 路径 b->a->t 表示 bat

语法

func NewTrie() *Trie

语法定义了一个名为 NewTrie() 的函数,用于初始化一个新的 Trie 实例,该实例具有一个根节点,该节点包含一个用于子节点的映射。

func (t *Trie) StartsWith(prefix string) (words []string)

语法定义了一个名为 StartsWith 的函数,该函数对于给定的前缀,通过 Trie 导航以识别共享该前缀的单词,方法是递归遍历从根到前缀的节点。它收集在该前缀下找到的单词,并将它们作为列表返回。

算法

  • 首先创建一个 TrieNode 类型结构,该结构具有一个映射来存储子节点。

  • 然后定义一个 Insert 函数,将单词添加到 Trie 中。

  • 开发一个 Search 函数,检查 Trie 中是否存在单词。

  • 构建一个 StartsWith 函数,查找具有给定前缀的所有单词。

  • 最后,设计一个 Print 函数来可视化 Trie 结构。

示例

在此示例中,我们使用 TrieNode 结构定义了一个 Trie 数据结构,其中包括一个用于存储子节点的映射和一个布尔值以标记单词的结尾。Insert 函数通过迭代字符并在需要时创建节点来帮助添加字符串。Search 函数遍历 Trie 以确定单词是否存在。最后,printTrie 函数以可视方式显示 Trie 的结构。

package main
import "fmt"
type TrieNode struct{ children map[rune]*TrieNode; isEnd bool }
type Trie struct{ root *TrieNode }
func NewTrie() *Trie { return &Trie{root: &TrieNode{children: make(map[rune]*TrieNode)}}}
func (t *Trie) Insert(word string) {
	node := t.root
	for _, c := range word {
     	if node.children[c] == nil { node.children[c] = &TrieNode{children: make(map[rune]*TrieNode)}}
    	node = node.children[c]
    }
	node.isEnd = true
}
func (t *Trie) Search(word string) bool {
	node := t.root
	for _, c := range word {
     	if node.children[c] == nil { return false }
    	node = node.children[c]
	}
	return node.isEnd
}
func printTrie(node *TrieNode, level int, prefix string) {
    if node == nil { return }
	fmt.Printf("%s%d\n", prefix, level)
	for c, childNode := range node.children {
    	printTrie(childNode, level+1, fmt.Sprintf("%s──", prefix))
    	fmt.Printf("%s%s\n", prefix, string(c))
    }
}
func main() {
	trie := NewTrie()
	words := []string{"apple", "app", "banana", "bat"}
	for _, w := range words { trie.Insert(w); }
	fmt.Println("\nTrie Structure:"); printTrie(trie.root, 0, "")
	fmt.Println("\nSearch 'app':", trie.Search("app")) 
	fmt.Println("Search 'banana':", trie.Search("banana")) 
	fmt.Println("Search 'batman':", trie.Search("batman"))
}

输出

Trie Structure:
0
──1
────2
──────3
────────4
──────────5
────────e
──────l
────p
──p
a
──1
────2
──────3
────────4
──────────5
────────────6
──────────a
────────n
──────a
────n
──────3
────t
──a
b

Search 'app': true
Search 'banana': true
Search 'batman': false

现实生活中的应用

  • 联系人或电话簿应用程序:尝试管理联系人信息可用于开发联系人或电话簿应用程序。Trie 数据结构允许通过其节点对联系人姓名中的特定字符进行编码,从而可以通过输入部分名称来搜索联系人。

  • IDE 中的自动完成功能:作为集成开发环境 (IDE) 中的普遍功能,代码自动完成功能需要简化的实现。Trie 有助于快速识别与输入前缀匹配的有效代码片段,从而实现简化的体验。

结论

Trie 数据结构是字符串操作的基本工具,提供有效的单词存储和检索。在本文中,我们探讨了 Trie 的概念,使用两种不同的方法在 Go 中实现了 Trie 数据结构。第一种方法强调插入和搜索,以突出 Trie 对字典或拼写检查器中单词查找的适用性。第二种方法通过实现前缀匹配引入了 Trie 的多功能性,这对于自动完成或建议等任务很有用。

更新时间: 2023年10月18日

564 次查看

开启你的 职业生涯

通过完成课程获得认证

开始学习
广告