1、Trie树

Trie树即字典树或前缀树,

2、实践

代码实践如下:

 package cn.edu.buaa.trie;

 import java.util.HashSet;

 /**
* @author zsm
* @date 2016年10月25日 上午11:03:13
* @version 1.0
* @parameter
* @return
*/
public class Trie {
private TrieNode trieRoot;
private int treeSize; public Trie() {
trieRoot = new TrieNode();
treeSize = 0;
} public TrieNode getRoot() {
return trieRoot;
} public int getTreeSize() {
return treeSize;
} /**
* 添加单词
*/
public void addWord(String word, int wordId) {
addWord(trieRoot, word, wordId);
} public void addWord(TrieNode root, String word, int wordId) {
// 输入单词为空
if (null == word || word.length() == 0) {
return;
} // 确定第一个字符在放在哪个孩子节点中
int k = TrieNode.getCharPosition(word.charAt(0)); // 该孩子为空,初始化
if (root.childNodes[k] == null) {
root.childNodes[k] = new TrieNode();
treeSize++;
root.childNodes[k].nodeChar = word.charAt(0);
}
// 单词出现在该孩子节点中
root.childNodes[k].wordSet.add(wordId); word = word.substring(1);
// 说明是最后一个字符,该词词频数加1
if (word.length() == 0) {
root.childNodes[k].freq++;
} else {
addWord(root.childNodes[k], word, wordId);
}
} /**
* 删除单词
*/
public void deleteWord(String word, int wordId) {
deleteWord(trieRoot, word, wordId);
} enum DELETERES {
FAIL_EMPTYWORLD, FAIL_WORLD_NOT_EXIST, SUCCESS
}; public DELETERES deleteWord(TrieNode root, String word, int wordId) {
// 输入单词为空
if (null == word || word.length() == 0) {
return DELETERES.FAIL_EMPTYWORLD;
} int k = TrieNode.getCharPosition(word.charAt(0)); // 第一个字符不在树中,说明没有要删除的单词
if (root.childNodes[k] == null) {
return DELETERES.FAIL_WORLD_NOT_EXIST;
} // 第一个字符在树中
DELETERES res;
{
word = word.substring(1);
// 找到该单词
if (word.length() == 0 && root.childNodes[k].freq > 0) {
root.childNodes[k].freq--;
res = DELETERES.SUCCESS;
} else {
res = deleteWord(root.childNodes[k], word, wordId);
} if (res == DELETERES.SUCCESS) {
// 从沿途节点移除该单词
root.childNodes[k].wordSet.remove(wordId);
// 没单词了,释放节点
if (root.childNodes[k].wordSet.size() == 0) {
root.childNodes[k] = null;
treeSize--;
}
}
return res;
}
} /**
* 修改单词
*/
public void updateWord(String newWord, String oldWord, int wordId) {
updateWord(trieRoot, newWord, oldWord, wordId);
} public void updateWord(TrieNode root, String newWord, String oldWord, int wordId) {
if (deleteWord(root, oldWord, wordId) == DELETERES.SUCCESS) {
addWord(root, newWord, wordId);
}
} /**
* 找以给定单词为前缀的所有单词的id
*/
public HashSet<Integer> searchPrefixWord(String word) {
return searchPrefixWord(trieRoot, word);
} public HashSet<Integer> searchPrefixWord(TrieNode root, String word) { HashSet<Integer> wordSet = new HashSet<Integer>(); // 输入单词为空
if (null == word || word.length() == 0) {
return wordSet;
} int k = TrieNode.getCharPosition(word.charAt(0));
// 单词里某个字符在树种不存在,说明没有该单词
if (root.childNodes[k] == null) {
return wordSet;
} word = word.substring(1); if (word.length() == 0) {
wordSet = root.childNodes[k].wordSet;
} else {
wordSet = searchPrefixWord(root.childNodes[k], word);
}
return wordSet;
} /**
* 统计给定单词出现的次数
*/
public int wordCount(String word) {
return wordCount(trieRoot, word);
} public int wordCount(TrieNode root, String word) { // 输入单词为空
if (null == word || word.length() == 0) {
return 0;
} int k = TrieNode.getCharPosition(word.charAt(0));
// 单词里某个字符在树种不存在,说明没有该单词
if (root.childNodes[k] == null) {
return 0;
} int count = 0;
word = word.substring(1); if (word.length() == 0) {
count = root.childNodes[k].freq;
} else {
count = wordCount(root.childNodes[k], word);
} return count;
}
} /**
* Trie树的节点<br>
* 假定单词都由26个英文字母组成,Trie树根节点不存字符
*/
class TrieNode {
// 孩子节点
public TrieNode[] childNodes;
// 该节点的字符
public char nodeChar; // 以该节点为结束的单词的词频
public int freq;
// 包含该节点的单词的id
public HashSet<Integer> wordSet; // 初始化
public TrieNode() {
childNodes = new TrieNode[CHILD_NUM];
freq = 0;
wordSet = new HashSet<Integer>();
} private static final int CHILD_NUM = 26; public static int getCharPosition(char ch) {
return (ch - 'a');
}
}

测试:

 package cn.edu.buaa.trie;

 /**
* @author zsm
* @date 2016年10月25日 下午3:12:02
* @version 1.0
* @parameter
* @return
*/
public class Main_Trie { public static void main(String[] args) {
// TODO Auto-generated method stub
Trie trie = new Trie();
String wd1 = "ab";
String wd2 = "ac";
String wd3 = "acd"; String wd4 = "add"; trie.addWord(wd1, 1);
trie.addWord(wd2, 2);
trie.addWord(wd2, 3);
trie.addWord(wd3, 4); // wd1,wd2,wd2,wd3
System.out.println(trie.wordCount(wd2));//
System.out.println(trie.wordCount(wd3));//
System.out.println(trie.getTreeSize());//
System.out.println(); trie.deleteWord(wd3, 4);
// wd1,wd2,wd2
System.out.println(trie.wordCount(wd2));//
System.out.println(trie.wordCount(wd3));//
System.out.println(trie.getTreeSize());//
System.out.println(); trie.addWord(wd3, 4);
// wd1,wd2,wd2,wd3
System.out.println(trie.wordCount(wd2));//
System.out.println(trie.wordCount(wd3));//
System.out.println(trie.getTreeSize());//
System.out.println(); trie.deleteWord(wd2, 2);
trie.deleteWord(wd2, 3);
// wd1,wd3
System.out.println(trie.wordCount(wd2));//
System.out.println(trie.wordCount(wd3));//
System.out.println(trie.getTreeSize());//
System.out.println(trie.searchPrefixWord("a"));// [1,4]
System.out.println(); trie.updateWord(wd3, wd4, 4);
// wd1,wd3
System.out.println(trie.searchPrefixWord("a"));// [1,4]
System.out.println(trie.wordCount(wd2));//
System.out.println(trie.wordCount(wd3));//
System.out.println(trie.wordCount(wd4));//
System.out.println(trie.getTreeSize());//
System.out.println(); trie.updateWord(wd4, wd3, 4);
// wd1,wd4
System.out.println(trie.searchPrefixWord("a"));// [1,4]
System.out.println(trie.wordCount(wd2));//
System.out.println(trie.wordCount(wd3));//
System.out.println(trie.wordCount(wd4));//
System.out.println(trie.getTreeSize());//
System.out.println();
}
}

3、参考资料

http://www.cnblogs.com/huangxincheng/archive/2012/11/25/2788268.html

Trie tree实践的更多相关文章

  1. 字典树(Trie Tree)

    终于要开始更新我的ACM学习之路了,不过没想到却是因为一次Java大作业,有趣,%yuan老师. 字典树是一种很简单的树形结构,主要用来进行词频统计,在算法竞赛中有时也会碰到. 字典树的基本思路是,通 ...

  2. 关于Trie Tree简单实现

    最近突然有兴致hiho一下了,实现了下trie tree,感觉而言,还是挺有意思的,个人觉得这货不光可以用来查单词吧,其实也可以用来替代Hash,反正查找,插入复杂度都挺低的,哈哈,啥都不懂,瞎扯.. ...

  3. 笔试算法题(39):Trie树(Trie Tree or Prefix Tree)

    议题:TRIE树 (Trie Tree or Prefix Tree): 分析: 又称字典树或者前缀树,一种用于快速检索的多叉树结构:英文字母的Trie树为26叉树,数字的Trie树为10叉树:All ...

  4. Phone List POJ 3630 Trie Tree 字典树

    Phone List Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 29416   Accepted: 8774 Descr ...

  5. 字典树(Trie Tree)

    在图示中,键标注在节点中,值标注在节点之下.每一个完整的英文单词对应一个特定的整数.Trie 可以看作是一个确定有限状态自动机,尽管边上的符号一般是隐含在分支的顺序中的.键不需要被显式地保存在节点中. ...

  6. hdu3724Encoded Barcodes(Trie tree)

    题目请戳这里 题目大意:给n个字符串,给m个询问,每个询问给k个条形码.每个条形码由8个小码组成,每个小码有相应的宽度,已知一个条形码的宽度只有2种,宽的表示1,窄的表示0.并且宽的宽度是窄的宽度的2 ...

  7. trie tree(字典树)

    hihocoder题目(http://hihocoder.com/problemset):#1014 trie树 #include <iostream> using namespace s ...

  8. Find the Clones Trie Tree

    Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 8306   Accepted: 3130 Description Doubl ...

  9. 字典树Trie Tree

    又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:利用字符串的公共前缀 ...

随机推荐

  1. Linux 多线程可重入函数

    Reentrant和Thread-safe 在单线程程序中,整个程序都是顺序执行的,一个函数在同一时刻只能被一个函数调用,但在多线程中,由于并发性,一个函数可能同时被多个函数调用,此时这个函数就成了临 ...

  2. linux 系统工具集

    Htop Htop是一款非常先进的交互式实时Linux进程监测工具.它非常类似Linux top命令,但是有一些丰富的功能特性,比如易于使用的界面,可用于管理进程.快捷键.进程的垂直和水平视图以及其他 ...

  3. [WPF系列]-DataBinding(数据绑定) 自定义Binding

    自定义Binding A base class for custom WPF binding markup extensions BindingDecoratorBase Code: public c ...

  4. 国内经典BI系统架构分析

    谈起商业智能BI,也许大家并不陌生,但你是否了解国内的各类BI系统架构? 自国内商业智能发展以来,就系统结构方面已经历了多次优化性的变革.目前国内商业智能BI系统的经典架构的模式包括数据层.业务层和应 ...

  5. 基于Azure构建PredictionIO和Spark的推荐引擎服务

    基于Azure构建PredictionIO和Spark的推荐引擎服务 1. 在Azure构建Ubuntu 16.04虚拟机 假设前提条件您已有 Azure 帐号,登陆 Azure https://po ...

  6. 【读书笔记《Bootstrap 实战》】6.单页营销网站

    我们已经掌握了很多实用 Bootstrap  的重要技能.现在,是时候拿出更多的创意来帮助客户实现他们全方位在线营销的愿望了.此次将带领大家做一个漂亮的单页高端营销网站. 主要任务如下: □ 一个大型 ...

  7. Spring远程调用技术<3>-Spring的HTTP Invoker

    前面提到RMI使用java标准的对象序列化机制,但是很难穿透防火墙.  另一方面,Hessian和Burlap能很好地穿透防火墙,但是使用私有的对象序列化机制. Spring提供的http invke ...

  8. PHP对文件数据的存储和检索

    @(主要是对文件的操作) 文件处理:php操作文件主要是写入和读取这两种.执行的步骤都是一样的. 1.打开这个文件.如果打不开就先创建它.2.将数据写入这个文件,或者将数据读出这个文件.3.关闭文件. ...

  9. Winform布局方式

    一.默认布局 ★可以加panel,也可以不加: ★通过鼠标拖动控件的方式,根据自己的想法布局.拖动控件的过程中,会有对齐的线,方便操作: ★也可选中要布局的控件,在工具栏中有对齐工具可供选择,也有调整 ...

  10. [转载]彻底弄清struct和typedef struct

    struct和typedef struct 分三块来讲述: 1 首先://注意在C和C++里不同 在C中定义一个结构体类型要用typedef: typedef struct Student { int ...