Trie树

68 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情

Trie树

Trie树,有很多别名:前缀数、字典树、单词查找数和键树,是一种树形结构,也是一种哈希树的变种。

典型的应用是统计和排序大量的字符串(不局限于字符串),经常被搜索系统用于文本词频的统计,自动补全或拼写检查等。

优点

最大限度地减少字符串的比较,查询效率比哈希表高。

核心思想

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

特性

  1. 根节点不包含任何字符,其他节点都有且只有一个字符
  2. 从根节点到某一节点路经的字符连接起来为该节点对应的字符串
  3. 每个节点子节点包含的字符都不同

Trie前缀树

描述

我们需要实现一个Trie树对象,包含的功能有:

  1. 初始化Trie树对象;
  2. 对空对象或已存在节点的Trie树新增新的节点
  3. 查询某个字符串字符是否存在
  4. 查询是否存在以某个前缀开头的字符串字符

分析

初始化Trie树对象,我们可以定义一个全局空对象;

插入操作循环需要新增的字符串,一个字符对应一个节点放入,逐层添加;

查询某个字符串是否存在和是否是以某个前缀开头功能有相似之处,不同的地方在于:是否存在某个前缀只要某个链路节点存在即可,而要判断某个字符串是否存在,还需要判断最后一个节点的是否有结束标志,是一个完整的数据链节点。

代码

var Trie = function() {
  this.children = {}
  this.searchPrefix = function (prefix) {
    let node = this.children
    for (const ch of prefix) {
      if (!node[ch]) {
        return false
      }
      node = node[ch]
    }
    return node
  }
};

/** 
 * @param {string} word
 * @return {void}
 */
Trie.prototype.insert = function(word) {
  let node = this.children
  for (let ch of word) {
    if (!node[ch]) {
      node[ch] = {}
    }
    node = node[ch]
  }
  node.isEnd = true
};

/** 
 * @param {string} word
 * @return {boolean}
 */
Trie.prototype.search = function(word) {
  const node = this.searchPrefix(word)
  return node && node.isEnd !== undefined
};

/** 
 * @param {string} prefix
 * @return {boolean}
 */
Trie.prototype.startsWith = function(prefix) {
  return this.searchPrefix(prefix)
};