Trie - tenji/ks GitHub Wiki

字典树

一、什么是字典树?

字典树,是一种空间换时间的数据结构,又称 Trie 树前缀树,是一种树形结构(字典树是一种数据结构),典型用于统计、排序、和保存大量字符串。所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高

可能大部分情况你很难直观或者有接触的体验,可能对前缀这个玩意没啥概念,可能做题遇到前缀问题也是暴力匹配蒙混过关,如果字符串比较少使用哈希表等结构可能也能蒙混过关,但如果字符串比较长、相同前缀较多那么使用字典树可以大大减少内存的使用和效率。一个字典树的应用场景:在搜索框输入部分单词下面会有一些神关联的搜索内容,你有时候都很神奇是怎么做到的,这其实就是字典树的一个思想。

字典树可以最大限度地减少无谓的字符串比较,用于词频统计和大量字符串排序。自带排序功能,使用中序遍历序列即可得到排序序列。但是如果字符很多相同前缀很少的话那字典树就没啥效率优势的(因为要一个一个访问节点)。

字典树的真实应用有很多,例如字符串检索、文本预测、自动完成,see also,拼写检查、词频统计、排序、字符串最长公共前缀、字符串搜索的前缀匹配、作为其他数据结构和算法的辅助结构等等,这里就不再介绍啦。

二、字典树的特性

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

三、设计实现字典树

3.1 类结构

class TrieNode {
    Map<Character, TrieNode> sonMap;
    boolean isEnd;
    public TrieNode() {
        sonMap = new HashMap<>();
    }
}

3.2 插入

public void insert(String word) {
    TrieNode node = root;
    for (int i = 0; i < word.length(); i++) {
        char ch = word.charAt(i);
        if(!node.sonMap.containsKey(ch)) {
            // 不存在则插入
            node.sonMap.put(ch, new TrieNode());
        }
        node = node.sonMap.get(ch);
    }
    node.isEnd = true;
}

3.3 查询

public boolean search(String word) {
    TrieNode node = root;
    for(int i = 0; i < word.length(); i++) {
        char ch = word.charAt(i);
        if(!node.sonMap.containsKey(ch)) {
            return false;
        }
        node = node.sonMap.get(ch);
    }
    // 必须标记为 true 证明有该字符串
    return node.isEnd == true;
}

3.4 前缀查找

public boolean startsWith(String prefix) {
    TrieNode node = root;
    for(int i = 0; i < prefix.length(); i++) {
        char ch = prefix.charAt(i);
        if(!node.sonMap.containsKey(ch))
        {
            return false;
        }
        node = node.sonMap.get(ch);
    }
    // 执行到最后一步即说明满足条件
    return true;
}

四、分析样例

4.1 题目描述

4.2 题目分析

4.3 代码实现

五、Leetcode 题目

参考链接