数据结构之字典树

Trie树,即字典树、前缀树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较。
总的来说,Trie的思想是以空间换空间,利用字符串的公共前缀来降低查找操作带来的时间开销以达到提高效率的目的。
主要性质

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

一.字典树的定义

  public class Trie{
    Trie[] root;              //孩子节点,代表下一个字符
    boolean isPause;   //是否终止 
    public Trie(){
      root = new Trie[26];
      isPause = false;
    }
  }

二.字典树的创建

void insert(String word)向前缀树中插入字符串 word 。
栗子:好比假设有b,abc,abd,bcd,abcd,efg,hii 这6个单词,那我们创建trie树就得到:

img

所以我们可以得到以下代码:

    /** Inserts a word into the trie. */
    public void insert(String word) {
        int length = word.length();
        Trie cur = this;
        for(int i = 0; i < length; i++){
            int index =word.charAt(i) - 'a';  //这里获得第i个字符的所在位置
            if(cur.children[index] == null){//如果该分支不存在,那么创建
                cur.children[index] = new Trie();
            }
            cur = cur.children[index]; //令cur指向当前单词,准备执行下一次操作
        }
       //单词插入完成后,需要将其此单词末尾字符的标记位 置true,代表此字符是单词的结尾
        cur.isPause = true;  
    }

三.字符串的查找

    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        int length = word.length();
        Trie cur = this;
        for(int i = 0; i < length; i++){
            int index = word.charAt(i) - 'a';
            //如果下一个字符匹配不上,直接返回。
            if(cur.children[index] == null){
                return false;
            }else{
                cur = cur.children[index];
            }
        }
        //遍历所有待查询单词的字符,返回待查询末尾字符是否为一个单词的结尾字符。
        return cur.isPause;
    }

四.字符串前缀的查找

boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false 。

    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        int length = prefix.length();
        Trie cur = this;
        for(int i = 0; i < length; i++){
            int index = prefix.charAt(i) - 'a';
          //如果下一个字符匹配不上,直接返回。
            if(cur.children[index] == null){
                return false;
            }else{
                cur = cur.children[index];
            }
        }  
        //这里和字符串查询的区别在于, 只要满足一个单词的前缀就返回true
        return true;
    }

五.代码汇总

class Trie {
    Trie[] children;
    boolean isPause;
    /** Initialize your data structure here. */
    public Trie() {
        children = new Trie[26]; 
        isPause = false;
    }
    
    /** Inserts a word into the trie. */
    public void insert(String word) {
        int length = word.length();
        Trie cur = this;
        for(int i = 0; i < length; i++){
            int index =word.charAt(i) - 'a';
            if(cur.children[index] == null){
                cur.children[index] = new Trie();
            }
            cur = cur.children[index];
        }
        cur.isPause = true;
    }
    
    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        int length = word.length();
        Trie cur = this;
        for(int i = 0; i < length; i++){
            int index = word.charAt(i) - 'a';
            if(cur.children[index] == null){
                return false;
            }else{
                cur = cur.children[index];
            }
        }
        return cur.isPause;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        int length = prefix.length();
        Trie cur = this;
        for(int i = 0; i < length; i++){
            int index = prefix.charAt(i) - 'a';
            if(cur.children[index] == null){
                return false;
            }else{
                cur = cur.children[index];
            }
        }
        return true;

    }
}

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.insert(word);
 * boolean param_2 = obj.search(word);
 * boolean param_3 = obj.startsWith(prefix);
 */

总结

时间复杂度:初始化为 O(1),其余操作为 O(|S|),其中 |S| 是每次插入或查询的字符串的长度。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容

  • Trie 又称作字典树、前缀树。 Trie 的结构 1、Trie 的设计很巧妙,它不像一般的字典那样,把一整个单词...
    李威威阅读 605评论 0 0
  • 字典树 字典树,又称 前缀树 或 trie树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不...
    清尘闲聊阅读 406评论 0 0
  •   字典树是简单的数据结构,从根节点到其他节点的每条路径都表示一串字符。 举例分析(POJ-2418https:/...
    idella阅读 183评论 0 0
  • 字典树 字典树是一种数据结构,可以用来进行词频统计,计算前缀个数等。它的每个节点的子节点都互不相同。 代码实现(P...
    idella阅读 257评论 0 0
  • 什么是Trie字典树 Trie 树,也叫“字典树”或“前缀树”。顾名思义,它是一个树形结构。但与二分搜索树、红黑树...
    端碗吹水阅读 482评论 0 1