`
zhaoyanfangeye
  • 浏览: 124823 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Trie 树 及Java实现

 
阅读更多
举个简单的例子。
   给你100000个长度不超过10的单词。对于每一个单词,我们要判断他出没出现过,如果出现了,第一次出现第几个位置。
这题当然可以用hash来,但是我要介绍的是trie树。在某些方面它的用途更大。比如说对于某一个单词,我要询问它的前缀是否出现过。这样hash就不好搞了,而用trie还是很简单。

   现在回到例子中,如果我们用最傻的方法,对于每一个单词,我们都要去查找它前面的单词中是否有它。那么这个算法的复杂度就是O(n^2)。显然对于100000的范围难以接受。现在我们换个思路想。假设我要查询的单词是abcd,那么在他前面的单词中,以b,c,d,f之类开头的我显然不必考虑。而只要找以a开头的中是否存在abcd就可以了。同样的,在以a开头中的单词中,我们只要考虑以b作为第二个字母的……这样一个树的模型就渐渐清晰了……

假设有b,abc,abd,bcd,abcd,efg,hii这6个单词,我们构建的树就是这样的。

对于每一个节点,从根遍历到他的过程就是一个单词,如果这个节点被标记为红色,就表示这个单词存在,否则不存在。
   那么,对于一个单词,我只要顺着他从根走到对应的节点,再看这个节点是否被标记为红色就可以知道它是否出现过了。把这个节点标记为红色,就相当于插入了这个单词。

   我们可以看到,trie树每一层的节点数是26^i级别的。所以为了节省空间。我们用动态链表,或者用数组来模拟动态。空间的花费,不会超过单词数×单词长度。(转自一大牛)

Trie树的java代码 实现如下:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


/** *//**
* A word trie which can only deal with 26 alphabeta letters.
* @author Leeclipse
* @since 2007-11-21
*/

public class Trie{

   private Vertex root;//一个Trie树有一个根节点

    //内部类
    protected class Vertex{//节点类
        protected int words;
        protected int prefixes;
        protected Vertex[] edges;//每个节点包含26个子节点(类型为自身)
        Vertex() {
            words = 0;
            prefixes = 0;
            edges = new Vertex[26];
            for (int i = 0; i < edges.length; i++) {
                edges[i] = null;
            }
        }
    }

 
    public Trie () {
        root = new Vertex();
    }

  
    /** *//**
     * List all words in the Trie.
     *
     * @return
     */

    public List< String> listAllWords() {
      
        List< String> words = new ArrayList< String>();
        Vertex[] edges = root.edges;
      
        for (int i = 0; i < edges.length; i++) {
            if (edges[i] != null) {
                     String word = "" + (char)('a' + i);
                depthFirstSearchWords(words, edges[i], word);
            }
        }       
        return words;
    }

     /** *//**
     * Depth First Search words in the Trie and add them to the List.
     *
     * @param words
     * @param vertex
     * @param wordSegment
     */

    private void depthFirstSearchWords(List words, Vertex vertex, String wordSegment) {
        Vertex[] edges = vertex.edges;
        boolean hasChildren = false;
        for (int i = 0; i < edges.length; i++) {
            if (edges[i] != null) {
                hasChildren = true;
                String newWord = wordSegment + (char)('a' + i);               
                depthFirstSearchWords(words, edges[i], newWord);
            }           
        }
        if (!hasChildren) {
            words.add(wordSegment);
        }
    }

    public int countPrefixes(String prefix) {
        return countPrefixes(root, prefix);
    }

    private int countPrefixes(Vertex vertex, String prefixSegment) {
        if (prefixSegment.length() == 0) { //reach the last character of the word
            return vertex.prefixes;
        }

        char c = prefixSegment.charAt(0);
        int index = c - 'a';
        if (vertex.edges[index] == null) { // the word does NOT exist
            return 0;
        } else {

            return countPrefixes(vertex.edges[index], prefixSegment.substring(1));

        }       

    }

    public int countWords(String word) {
        return countWords(root, word);
    }   

    private int countWords(Vertex vertex, String wordSegment) {
        if (wordSegment.length() == 0) { //reach the last character of the word
            return vertex.words;
        }

        char c = wordSegment.charAt(0);
        int index = c - 'a';
        if (vertex.edges[index] == null) { // the word does NOT exist
            return 0;
        } else {
            return countWords(vertex.edges[index], wordSegment.substring(1));

        }       

    }

   
    /** *//**
     * Add a word to the Trie.
     *
     * @param word The word to be added.
     */

    public void addWord(String word) {
        addWord(root, word);
    }

   
    /** *//**
     * Add the word from the specified vertex.
     * @param vertex The specified vertex.
     * @param word The word to be added.
     */

    private void addWord(Vertex vertex, String word) {
       if (word.length() == 0) { //if all characters of the word has been added
            vertex.words ++;
        } else {
            vertex.prefixes ++;
            char c = word.charAt(0);
            c = Character.toLowerCase(c);
            int index = c - 'a';
            if (vertex.edges[index] == null) { //if the edge does NOT exist
                vertex.edges[index] = new Vertex();
            }

            addWord(vertex.edges[index], word.substring(1)); //go the the next character
        }
    }

    public static void main(String args[])  //Just used for test
    {
    Trie trie = new Trie();
    trie.addWord("China");
    trie.addWord("China");
    trie.addWord("China");

    trie.addWord("crawl");
    trie.addWord("crime");
    trie.addWord("ban");
    trie.addWord("China");

    trie.addWord("english");
    trie.addWord("establish");
    trie.addWord("eat");
    System.out.println(trie.root.prefixes);
     System.out.println(trie.root.words);


  
     List< String> list = trie.listAllWords();
     Iterator listiterator = list.listIterator();
    
     while(listiterator.hasNext())
     {
          String s = (String)listiterator.next();
          System.out.println(s);
     }

  
     int count = trie.countPrefixes("ch");
     int count1=trie.countWords("china");
     System.out.println("the count of c prefixes:"+count);
     System.out.println("the count of china countWords:"+count1);


    }
}
运行:
C:\test>java   Trie
10
0
ban
china
crawl
crime
eat
english
establish
the count of c prefixes:4
the count of china countWords:4

文章来自:http://oivoiv.blog.163.com/
分享到:
评论

相关推荐

    Trie树(字典树)的介绍及Java实现

    在Java中实现Trie树,首先定义节点类`TrieNode`,包括指向26个子节点的数组(表示26个英文字母),字符数据成员`data`,以及词频计数器`freq`。例如: ```java public class TrieNode { public TrieNode[] ...

    java数组-基于java实现的双数组Trie树.zip

    本项目聚焦于利用Java实现的双数组Trie树,这是一种在字符串处理和搜索中广泛使用的数据结构。 Trie树,又称“前缀树”或“字典树”,是一种用于存储键值对的数据结构,特别适用于字符串。它的主要特点是能以O(1)的...

    基于Trie树模仿谷歌百度搜索框提示

    在Java中实现Trie树,我们需要定义一个TrieNode类,它包含一个字符数组(代表子节点)和一个布尔值(表示当前节点是否为单词的结尾)。我们还需要一个方法来插入字符串到Trie树中,这个过程涉及遍历字符串的每个字符...

    基于Java链表实现的字典树(trie)

    基于Java链表实现的字典树(trie),实现了增删改查等功能,它说摘要必须大于50字我还能说啥啥啥啥

    Java实现字典树TrieTree

    总的来说,Java实现的字典树TrieTree是一个强大的工具,尤其适用于处理大量字符串数据,如四六级高频词汇的存储和查询。通过理解和运用这种数据结构,我们可以提高算法效率,优化应用程序的性能。

    实现Trie_java_

    在Java中实现Trie数据结构,可以帮助我们快速处理大量字符串数据,例如在搜索引擎中进行关键词索引或者在自动补全功能中提供快速建议。 Trie的基本思想是利用字符串的公共前缀来节省存储空间。每个节点代表一个字符...

    trie:Trie数据结构的Java实现

    Prefix Trie数据结构的Java实现。 介绍 尝试是类似于基于有序树的数据结构的地图,可快速搜索O(k)的顺序,其中k是键的长度。 阅读有关trie的更多信息。 动机 它最初是为在我的Android应用程序T9 App Launcher中使用...

    DoubleArrayTrie:高级结构双数组Trie树(DoubleArrayTrie) java实现

    DoubleArrayTrie Java编写的DoubleArrayTrie介绍用法// construct and buildDoubleArrayTrie dat = new DoubleArrayTrie(); for(String word: words) { dat.Insert(word); } System.out.println(dat.Base.length); ...

    字典树实例--java实现

    这个实例是用Java语言实现的,我们将深入探讨字典树的工作原理和Java实现的关键点。 首先,字典树的核心概念是利用节点来存储字符串的字符,每个节点可能有多个子节点,对应于下一个可能的字符。根节点通常不包含...

    JAVA实现的中文分词程序

    在Java程序中,通常会通过I/O操作读取这些词典文件,并根据其内容构建数据结构,如哈希表或者Trie树,以优化查询效率。 描述中提到的“导入词典”功能存在问题,这可能意味着程序在加载词典时遇到困难,可能是由于...

    AC算法(java实现)

    Trie树可以快速定位到模式串的某个前缀,而失败指针则用于在当前字符不匹配时,快速回溯到可能匹配的下一个位置,无需从根节点重新开始。 在Java中实现AC算法,首先需要创建一个表示Trie节点的数据结构,通常包含...

    字典树~java语言

    在这个"trim"压缩包文件中,可能包含了一个用Java实现字典树的项目或代码示例。你可以解压后查看源码,了解如何将上述理论知识应用到实际编程中。同时,学习如何读取文件、构建字典树,以及执行插入、搜索和删除操作...

    Java实现单词查询程序

    可能的选择有哈希表(HashMap)、二叉搜索树(如AVL或红黑树)或Trie树(字典树),这些数据结构能快速定位到目标单词并返回翻译。 5. **文件I/O操作**:如果使用文本文件存储词典,那么Java的FileInputStream和...

    [图灵社区]《深度学习搜索引擎开发:Java实现》源代码.zip

    高效的排序和搜索算法是关键,如Trie树、B树等。 2. **深度学习框架**:可能使用TensorFlow、PyTorch或Deeplearning4j等Java友好的深度学习框架,实现特征提取、模型训练和预测。 3. **自然语言处理(NLP)**:Java ...

    java实现敏感词过滤

    本项目是用Java实现的一个敏感词过滤工具,它能对输入的字符串进行检查,并返回其中的敏感词汇。以下是关于这个Java敏感词过滤实现的详细知识讲解。 首先,我们要理解敏感词过滤的基本原理。通常,敏感词过滤系统会...

    Java 实现文章汉字关键词(违禁词)识别

    总结来说,Java实现文章汉字关键词(违禁词)识别需要结合多种数据结构和算法,如哈希表、Trie树、分词库和过滤算法。通过合理的设计和优化,我们可以构建出高效、准确的违禁词检测系统,满足内容审核的需求。

    Java实现编译原理DFA图转换

    给定算术表达式的DFA图,利用Java语言构建Trie树,实现对输入文法的判断

    模糊匹配算法java实现

    例如,可以使用Trie树或AC自动机构建索引来加速前缀匹配。 - **启发式算法**:对于复杂问题,可以采用启发式算法,如A*搜索、Beam搜索等,以平衡计算时间和匹配质量。 - **并行计算**:利用Java的并发库,如`java....

    关于tire树

    #### 二、Trie树的结构与实现 Trie树的基本结构包括以下几点: 1. **节点结构**:每个节点代表一个字符,且通常包含指向子节点的指针数组或哈希表来表示可能的下一个字符。 2. **根节点**:通常不包含任何字符,它...

Global site tag (gtag.js) - Google Analytics