有意思的树--前缀树

前缀树

前缀树(Trie,发音为"try")是一种特殊的树状数据结构,用于有效地存储和检索一组字符串,通常是一组字符串集合。前缀树的主要特点是能够高效地支持按照前缀来搜索和匹配字符串。

前缀树的基本特性如下:

  1. 树结构:前缀树是一个树状结构,通常是一棵多叉树,每个节点代表一个字符,从根节点到叶子节点的路径构成一个字符串。
  2. 每条路径代表一个字符串:从根节点到叶子节点的路径表示一个完整的字符串。树中的每个叶子节点都对应一个存储的字符串。
  3. 共享前缀:前缀树的节点可以共享相同的前缀。这意味着在树的不同分支上,相同的前缀部分只会存储一次,从而节省了空间。
  4. 高效的前缀匹配:前缀树非常适合用于查找具有特定前缀的字符串。通过从根节点开始,沿着树上的路径移动,可以快速找到具有特定前缀的字符串。
  5. 快速插入和删除:前缀树支持快速插入和删除操作,因为它通常只涉及到添加或删除节点。

前缀树的应用广泛,特别是在字符串处理领域,如自动完成、拼写检查、IP地址查找、单词搜索游戏和路由表查找等。它还在许多编程问题中发挥了关键作用,例如搜索引擎中的关键字搜索和字典校验等。前缀树的时间复杂度通常是与搜索字符串的长度成正比的,因此对于大型字符串集合,它通常具有较好的性能。

应用场景

前缀树(Trie)在许多字符串处理和搜索问题中都有广泛的应用场景。以下是一些常见的前缀树使用场景:

  1. 自动完成(Autocomplete) :前缀树常用于实现自动完成功能,例如搜索引擎的搜索建议、输入框的建议提示等。用户在输入时,前缀树可以快速查找以输入前缀开头的可能选项。
  2. 拼写检查(Spell Checking) :前缀树可用于实现拼写检查功能。它可以检查输入的单词是否存在于字典中,或者建议类似的正确拼写。
  3. 单词搜索游戏(Word Search Games) :前缀树可以用于单词搜索游戏,如字谜游戏或填字游戏,以确定是否可以从给定的字母网格中找到特定单词。
  4. IP地址查找(IP Address Lookup) :前缀树可以用于高效地查找IP地址和子网掩码,以确定数据包应该路由到哪个目标。
  5. URL路由(URL Routing) :在Web应用程序中,前缀树可以用于路由URL,根据URL路径确定要执行的处理程序或控制器。
  6. 字典实现(Dictionary Implementation) :前缀树可用于实现字典数据结构,允许高效地插入、删除和搜索单词。
  7. 统计词频(Count Word Frequency) :前缀树可以用于统计一组文本中单词的频率,例如在搜索引擎中确定搜索关键字的热门程度。
  8. 联系人搜索(Contact Search) :在手机或电子邮件应用程序中,前缀树可以用于快速搜索联系人列表。
  9. 文件系统路径查找(File System Path Lookup) :前缀树可用于查找文件系统中的文件和目录路径,以便在文件浏览器中快速导航。
  10. 编程问题解决:前缀树在解决编程问题时也非常有用,如查找最长公共前缀、查找所有具有相同前缀的单词等。

前缀树示意图

总之,前缀树在需要高效存储和检索字符串数据的场景中具有广泛的应用,能够加速搜索和匹配操作,提高程序性能。它在许多计算机科学和软件工程领域都是一个强大的工具。

前缀树是一种树状数据结构,通常用于存储一组字符串,其中每个节点代表一个字符,从根节点到叶子节点的路径构成一个字符串。以下是一个简单的文字示意图,描述了一个前缀树的结构:

在这个示意图中,前缀树包含了以下字符串:"app"、"apple"、"boss"、"boy"的单词

  • 根节点代表空字符串。
  • 从根节点开始,有两个分支分别代表字符 "a"、"b" 。
  • 从 "a" 分支出来,有个分支分别代表字符 "p",构成字符串 "app" 和 "apple"。
  • 从 "b" 分支出来,有两个分支分别代表字符 "y" 和 "s",构成字符串 "boy" 和 "boss"。
  • 后续的字符按此方式插入

前缀树的节点可以共享前缀,例如 "app" 和 "apple" 共享前缀 "app",这使得前缀树非常节省空间。前缀树的叶子节点通常用来标记一个完整的单词。

这个示意图演示了前缀树的基本结构,但实际的前缀树可能更复杂,包括更多的节点和更多的字符串。前缀树的主要用途之一是快速查找以特定前缀开头的字符串,以及高效存储和检索大量字符串数据。 如图所示,该树包含了

  1. 插入字符串:从字段树的根节点开始,如果子节点存在,继续处理下一个字符,如果子节点不存在,则创建一个子节点到children的相应位置,沿着指针继续向后移动,处理下一个字符,以插入'cad'为例
  2. 查找前缀:从根节点开始,子节点存在,则沿着指针继续搜索下一个子节点,直到最后一个,如果搜索到了前缀所有字符,说明字典树包含该前缀。子节点不存在就说明字典树中不包含该前缀,返回false。
  3. 查找字符串:和查找前缀一样,只不过最后返回的节点的isEnd是true,也就是说字符串正好是字典树的一个分支
  • 复杂度分析:时间复杂度,初始化为 O(1),其余操作为 O(S),s为字符串的长度。空间复杂度为O(T),T为字符集的大小,

代码

ini 复制代码
class TrieNode {
  constructor() {
    this.children = {}; // 存储子节点
    this.isEndOfWord = false; // 标记是否是单词的结尾
    this.num = 0
  }
}

class Trie {
  constructor() {
    this.root = new TrieNode(); // 创建根节点
  }

  // 向前缀树中插入一个字符串
  insert(word) {
    let node = this.root;
    for (let i = 0; i < word.length; i++) {
      const char = word[i];
      if (!node.children[char]) {
        node.children[char] = new TrieNode();
      }
      node = node.children[char];
    }
    node.isEndOfWord = true; // 标记单词结尾
  }

  // 检查前缀是否存在于前缀树中
  startsWith(prefix) {
    let node = this.root;
    for (let i = 0; i < prefix.length; i++) {
      const char = prefix[i];
      if (!node.children[char]) {
        return false; // 前缀不存在
      }
      node = node.children[char];
    }
    return true; // 前缀存在
  }

  // 检查一个完整的单词是否存在于前缀树中
  search(word) {
    let node = this.root;
    for (let i = 0; i < word.length; i++) {
      const char = word[i];
      if (!node.children[char]) {
        return false; // 单词不存在
      }
      node = node.children[char];
    }
    node.num += 1 //每被查一次次数就+1
    return node.isEndOfWord; // 如果是单词的结尾,返回true
  }
}

使用

arduino 复制代码
const trie = new Trie();
trie.insert("apple");
console.log(trie.search("apple")); // 输出 true
console.log(trie.search("app")); // 输出 false

我们可以看看树的结构

该树元素即为层层嵌套的字母树,包含了对应的children、isEndOfWord和num属性,有什么需要记录的都可以通过添加属性来进行。而代码的理解还是比较简单的,没有什么复杂的操作,是以空间换时间的一种算法。

更复杂的一些英文字符的高亮即为将英文字符切割为数组,之后一个一个字母注入进前缀树中,添加同级的属性style,加入相应的样式,即可实现特定字符高亮。

好啦,这是简单的前缀树算法,也算介绍给大家伙了。

相关推荐
sp_fyf_202411 分钟前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
香菜大丸32 分钟前
链表的归并排序
数据结构·算法·链表
jrrz082832 分钟前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
oliveira-time43 分钟前
golang学习2
算法
南宫生2 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
懒惰才能让科技进步2 小时前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
Ni-Guvara3 小时前
函数对象笔记
c++·算法
泉崎3 小时前
11.7比赛总结
数据结构·算法
你好helloworld3 小时前
滑动窗口最大值
数据结构·算法·leetcode
AI街潜水的八角4 小时前
基于C++的决策树C4.5机器学习算法(不调包)
c++·算法·决策树·机器学习