常用算法之Trie【字典树,前缀树】

Trie中文名又叫做字典树,前缀树等,因为其结构独有的特点,经常被用来统计,排序,和保存大量的字符串,经常见于搜索提示,输入法文字关联等,当输入一个值,可以自动搜索出可能的选择。当没有完全匹配的结果时,可以返回前缀最为相似的可能。

其实腾讯的面试题有一个:如何匹配出拼写单词的正确拼写。其实用匹配树非常合适。

基本性质:

1.根节点不含有字符,其余各节点有且只有一个字符。

2.根节点到某一节点中经过的节点存储的值连接起来就是对应的字符串。

3.每一个节点所有的子节点的值都不应该相同。

借用一下维基百科上的一张图片:

看图还是蛮好理解的。但是我们应该怎么操作呢。

应为英文有26个字母,所以每个单词的每个位置都可能有26种取法,因此,我们可以为每个节点去26个子节点:

public class TrieNode {
    public static final int NUM_OF_LETTER = 26;

    private TrieNode[] childNodes = new TrieNode[NUM_OF_LETTER];
    private int freg;
    private boolean isEnd;
    private char varChar;

    /**
     * @param words
     * @return 不可用返回true  否则为可用
     */
    private static boolean checkWordsLenght(char[] words) {
        return (words.length == 0) || (words == null);
    }

    public static void addNode(TrieNode root, char[] words) {
        if (checkWordsLenght(words)) {
            return;
        }

        int index = words[0] - 'a';
        if (root.childNodes[index] == null) {
            root.childNodes[index] = new TrieNode();
            root.childNodes[index].varChar = words[0];
        }

        root.childNodes[index].freg++;
        words = Arrays.copyOfRange(words, 1, words.length);
        if (checkWordsLenght(words)) {
            root.isEnd = true;
            return;
        }
        addNode(root.childNodes[index], words);
    }

    public static void deleteNode(TrieNode root, char[] words) {
        if (checkWordsLenght(words) || (root == null)) {
            return;
        }

        int index = words[0] - 'a';
        if (root.childNodes[index] == null) {
            return;
        }

        root.childNodes[index].freg--;
        if (root.childNodes[index].freg == 0) {
            root.childNodes[index] = null;
        }

        words = Arrays.copyOfRange(words, 1, words.length);
        if (checkWordsLenght(words)) {
            root.childNodes[index] = null;
        }
        deleteNode(root.childNodes[index], words);
    }

    public static int getCountOfWords(TrieNode root, char[] words) {
        if (checkWordsLenght(words) || (root == null)) {
            return 0;
        }
        int index = words[0] - 'a';
        if (root.childNodes[index] == null) {
            return 0;
        }

        words = Arrays.copyOfRange(words, 1, words.length);
        if (checkWordsLenght(words)) {
            return root.freg;
        }

        return getCountOfWords(root.childNodes[index], words);
    }
}

里面有个很逗比的事情,我觉得可能是源代码编写人员犯错误。我们知道 Arrays.copyOfRange 有一个from和to的形参,意思是从索引为from开始复制,到索引to 结束,但是,看源码,我们可以看到它复制的内容长度是:to - from;当我们需要拷贝 0到 5的内容时,需要拷贝6个值,但计算确实5,很明显少了一个,所以,我们编码是需要注意一下。 其余看代码应该都懂的。

时间: 2024-12-28 09:21:34

常用算法之Trie【字典树,前缀树】的相关文章

9-11-Trie树/字典树/前缀树-查找-第9章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第9章  查找 - Trie树/字典树/前缀树(键树) ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.Scanf.c        相关测试数据

【数据结构】字典树/Trie树/前缀树 - 字符串的统计、排序和保存

字典树 描述 字典树,又称单词查找树.Trie树.前缀树,是一种树形结构,是一种哈希树的变种. 典型应用是用于统计.排序和保存大量的字符串(但不仅限于字符串). 常见操作有插入和查找,删除操作少见. 性质 根节点不包含字符 除根节点外每一个节点都只包含一个字符 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串 每个节点的所有子节点包含的字符都不相同 优点 利用字符串的公共前缀来减少查询时间 最大限度地减少无谓的字符串比较 查询效率比哈希树高 自带字典序排序 直接判断重复,或者记

算法初级面试题07——前缀树应用、介绍和证明贪心策略、拼接字符串得到最低字典序、切金条问题、项目收益最大化问题、随时取中位数、宣讲会安排

第六课主要介绍图,不经常考,故今天先讲第七课的内容,介绍比较常考的树和贪心算法 介绍前缀树 何为前缀树? 如何生成前缀树? 可以查有多少个字符串以"be"为前缀. 如果要判断有没有"be"这个节点,每个节点上加上一个数据项,有多少个字符串以当前节点结尾的(可以查加了多少次特定字符串). 给一个字符串.返回多少个字符串以这个为前缀. 再加一个数据项,记录该节点被划过多少次. 大概实现: 删除逻辑: 根据path是否变为0,来判断是否继续往下删. 可以解决以下问题: 一

LeetCode OJ:Implement Trie (Prefix Tree)(实现一个字典树(前缀树))

Implement a trie with insert, search, and startsWith methods. 实现字典树,前面好像有道题做过类似的东西,代码如下: 1 class TrieNode { 2 public: 3 // Initialize your data structure here. 4 TrieNode():isLeaf(false) 5 { 6 for(auto & t : dic){ 7 t = NULL; 8 } 9 } 10 TrieNode * di

[LeetCode] Implement Trie (Prefix Tree) 实现字典树(前缀树)

Implement a trie with insert, search, and startsWith methods. Note:You may assume that all inputs are consist of lowercase letters a-z. http://dongxicheng.org/structure/trietree/

【算法学习笔记】57. 前缀树 字典序优化技巧 STL学习 SJTU OJ 1366 前缀匹配

Description 给出一个总字符个数大小不超过1,000,000的字典(这个字典的单词顺序不为字典序)和不超过1000个长度不超过1000的前缀,输出字典中匹配该前缀,字典序为K_i的单词在字典中的位置. 所有单词都为小写字母. Input Format 第一行: 两个整数N,M,分别表示字典中的单词个数和需要查询的前缀数. 接下来N行:每行一个字符串,表示字典中的单词. 接下来M行,每行一个K_i, P_i, P_i表示查询的前缀,K_i表示满足这个前缀在字典序中的位置. Output

【数据结构】前缀树/字典树/Trie

[前缀树] 用来保存一个映射(通常情况下 key 为字符串  value 为字符串所代表的信息) 例如:一个单词集合 words = {  apple, cat,  water  }   其中 key 为单词      value 代表该单词是否存在 words[ 'apple' ] = 存在     而     word[ ' abc' ] = 不存在 图示:一个保存了8个键的trie结构,"A", "to", "tea", "ted

支持中文的基于词为基本粒度的前缀树(prefix trie)实现

Trie树,也叫字典树.前缀树.可用于”predictive text”和”autocompletion”,亦可用于统计词频(边插入Trie树边更新或添加词频). 在计算机科学中,trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串.与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定.一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串.一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相

支持中文的基于词为基本粒度的前缀树(prefix trie)python实现

Trie树,也叫字典树.前缀树.可用于"predictive text"和"autocompletion".亦可用于统计词频(边插入Trie树边更新或加入词频). 在计算机科学中.trie,又称前缀树或字典树.是一种有序树,用于保存关联数组,当中的键一般是字符串.与二叉查找树不同.键不是直接保存在节点中,而是由节点在树中的位置决定.一个节点的全部子孙都有同样的前缀,也就是这个节点相应的字符串,而根节点相应空字符串. 普通情况下,不是全部的节点都有相应的值,仅仅有叶子