• 11-字典树 Trie


    学习资源:慕课网liyubobobo老师的《玩儿转数据结构》


    1、简介

    ​ 又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。查询每个条目的时间复杂度,和字典中一共有多少条目无关,只与说查询的条目的长度有关。时间复杂度为O(w),w为查询单词的长度!

    • 根结点不包含字符,除根结点外每一个结点都只包含一个字符
    • 从根结点到某一结点,路径上经过的字符连接起来,为该结点对应的字符串;所以这条分支上可能有一个字符串,也可能有若干个字符串
    • 每个结点的所有子结点包含的字符都不相同
    • 从根结点遍历到叶子结点即是一个单词;也有的单词不是到叶子结点,此时这个单词的最后一个结点需要特殊标记

    2、原理分析

    • 如果字典树中只储存英文单词,那每个结点至多有26个指向下个结点的"指针"

    image-20200619123717919

    class Node{
    	char C;   // 当前结点存储的字符
    	Node next[26];  // 当前结点的"指针",指向下一个结点的映射
    }
    
    • 如果存储情况复杂(语种多样),那么每个结点应有若干个指向下个结点的指针,此时可以使用一个Map记录当前结点的"指针"
    class Node{
    	char C;
    	Map<char, Node> next;
    }
    
    • 每一个结点不需要存储具体的字符,在"指针"上存储当前结点指向的字符更合理

    image-20200619124733096

    class Node{
    	char C;
    	Map<char, Node> next;
    }
    
    • 每一个结点需要设计一个标记,来记录从根结点到当前结点是否为一个单词
    image-20200516171142541
    class Node{
    	boolean isWord;
    	Map<char, Node> next;
    }
    

    3、实现

    3.1、基础部分代码

    public class Trie {
    
        private class Node{
    
            boolean isWord;
            TreeMap<Character, Node> next ;
    
            public Node(boolean isWord) {
    
                this.isWord = isWord;
                next = new TreeMap<>();
            }
    
            public Node(){
                this(false);
            }
        }
    
        private Node root;
        private int size;
    
        public Trie(){
    
            root = new Node();
            size = 0;
        }
    
        public int getSize() {
            return size;
        }
    
    }
        
    

    3.2、添加字符串

    从根结点,向下遍历需要添加单词的每一个字符,如果当前结点存在指向字符的"指针"就跳过,不存在则创建(向Map中put)。

    public void add(String word){
        
        Node cur = root;
        for(int i = 0; i< word.length(); i++){
            
            char c = word.charAt(i);
            if(cur.next.get(c) == null){
                cur.next.put(c, new Node());
            }
            cur = cur.next.get(c);
        }
        if (!cur.isWord){
            
            cur.isWord = true;
            size++;
        }
    }
    

    3.3、查询字符串

    和添加操作差不多

    public boolean contains(String word){
        
        Node cur = root;
        for(int i = 0; i<word.length(); i++){
            
            char c = word.charAt(i);
            if(cur.next.get(c) == null){
                return false;
            }
            cur = cur.next.get(c);
        }
        
        return cur.isWord;
    }
    

    3.4、前缀搜索

    查询在Trie中是否有单词以prefix为前缀

    public boolean isPrefix(String prefix){
        
        Node cur = root;
        for (int i = 0; i < prefix.length(); i++) {
            
            char c = prefix.charAt(i);
            if(cur.next.get(c) == null){
                return false;
            }
            cur = cur.next.get(c);
        }
        
        return true;
    }
    
  • 相关阅读:
    OpenCV中的绘图函数
    整理不错的opencv博客
    opencv中的函数
    这是一个学习前端技术的网站
    HDU1520 Anniversary party(树形DP入门)
    CF1255C League of Leesins(图论)
    HDU4725 The Shortest Path in Nya Graph(最短路分层)
    1288C Two Arrays
    CF1294D MEX maxiszing
    CF1295C Obtain the String
  • 原文地址:https://www.cnblogs.com/sout-ch233/p/13178005.html
Copyright © 2020-2023  润新知