`
zhaoyanfangeye
  • 浏览: 122716 次
  • 性别: 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实现

    Trie树,又称字典树或前缀树,关于它的结构就不详细介绍了。Trie树在单词统计、前缀匹配等很多方面有很大用处...下面这篇文章主要介绍了Trie树,以及Java实现如何Trie树,有需要的朋友可以参考借鉴,下面来一起看看吧。

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

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

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

    java数组 java数组_基于java实现的双数组Trie树

    Java实现字典树TrieTree

    Java实现字典树TrieTree,可用于计算出四六级试题的高频词.

    trie:Trie数据结构的Java实现

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

    Java中实现双数组Trie树实例

    主要介绍了Java中实现双数组Trie树实例,双数组Trie就是一种优化了空间的Trie树,本文给出了实现代码、测试代码和测试结果,需要的朋友可以参考下

    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实现编译原理DFA图转换

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

    concurrent-patricia-trie:一个用 Java 实现的并发非阻塞 patricia 树

    在 Java 中实现的并发非阻塞 patricia 树。 此树支持整数键并使用基于边缘的锁定来改进内存和性能。 这是作为德切夫博士在 UCF 的并行算法和编程 (COP4520) 课程的最终项目完成的。 该存储库还包括一篇用 LaTeX 编写...

    WordTrie.java

    Java字典树实现。 精简优化版处理。适合Java屏蔽字并进行。进行检测并处理的情况

    Trie:Java中的Trie和Levenshtein距离混合实现,可实现极快的前缀字符串搜索和字符串相似性

    Java中的Trie和Levenshtein距离混合实现,可实现极快的前缀字符串搜索和字符串相似性。 作者:Umberto Griffo 推特:@UmbertoGriffo内容特里定义Trie [1]是使用字符串作为键的有序树数据结构。 这是一种有效的信息...

    一棵Java字典树(trie)和它的增删改查

    一棵用List来存储子结点的字典树——当然,也可以用哈希表等形式存储。 这篇笔记记录了构建思路,文末是源码 一、构建思路 Step1 设计结点——数据结构 Step2 实现相应的操作方法——增删改查 Step1 设计结点 我们...

    suffixTrie.zip

    后缀Trie树的java实现 标签:suffixTrie

    详解字典树Trie结构及其Python代码实现

    字典树(Trie)可以保存一些字符串-&gt;值的对应关系。基本上,它跟 Java 的 HashMap 功能相同,都...至于Trie树的实现,可以用数组,也可以用指针动态分配,我做题时为了方便就用了数组,静态分配空间。 Trie树,又称单词

    concurrent-trees:Java的并发基数树和后缀树

    基数树(也称为 patricia trie、radix trie或紧凑前缀树)是一种空间优化的树数据结构,它允许仅使用键的前缀插入键(以及与这些键相关联的可选值)以供后续查找而不是整个密钥。 基数树在字符串或文档索引和扫描...

    Java超详细!Java实现数据结构PPT课件

    复杂度 时间复杂度 空间复杂度 线性数据结构动态数组(ArrayList) ...Trie 线性+树形数据结构 集合(HashSet) 映射(HashMap、LinkedHashMap) 二叉堆(BinaryHeap) 优先级队列(PriorityQueue)

    自适应基数树:Java中快速且节省空间的基数树

    实施为Java NavigableMap的自适应基数树 该库基于ICDE 2013“自适应基数树:主存数据库的ARTful索引”,以的形式提供了自适应基数树(ART)的实现。 在有序数据结构的空间中,特别有趣,因为它们的高度和时间...

    TnS-Patricia-Trie:Java的灵活的patricia trie实现,提供丰富的功能和与前缀相关的操作

    Java的灵活的实现,提供了与前缀相关的操作的丰富功能。 它实现了接口,并且可以使用任何类型的对象作为键,只要可以通过专门的BitwiseComparator将它们按位进行比较BitwiseComparator 。 与相比,它具有相对的性能...

    javascript trie前缀树的示例

    Trie树(来自单词retrieval),又称前缀字,单词查找树,字典树,是一种树形结构,是一种哈希树的变种,是一种用于快速检索的多叉树结构。 它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。 Trie...

    Routing-Scheme-using-Binary-Trie:网络路由方案的实现

    使用BinaryTrie的路由方案网络路由方案的实现: 每个路由器都有一个IP地址,并且通过使用二进制特里(trie)的最长前缀匹配将数据包转发到下一跳路由器。 使用斐波那契堆为无向图实现Dijkstra的单一源最短路径(ssp...

Global site tag (gtag.js) - Google Analytics