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. jQuery 3.0的buildFragment

    在 jQuery3.0中,buildFragment 是一个私有函数,用来构建一个包含子节点 fragment 对象.这个 fragment 在 DOM1 中就已经有了,所有浏览器都支持.当频繁操作( ...

  2. iptables详解

    Netfilter包含有三种表,三种表下共包含有五种链,链下面包含各种规则.即表包含若干链,链包含若干规则.  (一)三种表为:filter   nat  mangle 1.filter:处理与本机有 ...

  3. 如何用python在Windows系统下,生成UNIX格式文件

    平时测试工作中,少不了制造测试数据.最近一个项目,我就需要制造一批可在UNIX下正确读取的文件.为确保这批文件能从FTP下载成功,开发叮嘱我:“文件中凡是遇到换行,换行符必须是UNIX下的LF,而不是 ...

  4. PHP实现多图片上传

    PHP实现多图片上传 今天在工作中遇到了一个需求:一个表单实现多个上传图片,类似于QQ空间上传照片的模式.即:可以一次性上传多个图片,但是封面图片只有一个. 最先,最重要的事,在服务器上对文件进行读写 ...

  5. 新书《编写可测试的JavaScript代码 》出版,感谢支持

    本书介绍 JavaScript专业开发人员必须具备的一个技能是能够编写可测试的代码.不管是创建新应用程序,还是重写遗留代码,本书都将向你展示如何为客户端和服务器编写和维护可测试的JavaScript代 ...

  6. 为什么目前没有"成熟"的cookie插件?

    一.序言 最近真是挺忙的啊,导致也挺久没有时间来看看园中各位大神的文章,只能感慨业务真尼玛的多,所以在此写下一篇文章来大话最近工作和学习上面的一点点收获体会,希望大家能够有所收获,这篇文章虽然说是一篇 ...

  7. TAC 坦克队

    The Art of Code 团队成员 组长:   031402330吴宇轩 组员:   031402509胡泽善   031402224彭 巍   031402230张建明   031402508 ...

  8. iOS常用 --- NSDictionary 与 NSMutableDictionary

    一.NSDictionary 字典的两种创建方法 NSDictionary *dic1 =[[NSDictionary alloc]init]; 2 // 或: 3 NSDictionary *dic ...

  9. 为什么print在python3中变成了函数?

    转自:http://www.codingpy.com/article/why-print-became-a-function-in-python-3/ 在Python 2中,print是一个语句(st ...

  10. javaScript获取url中的参数

    var urlTools = { //获取RUL参数值 getUrlParam: function(name) { /*?videoId=identification */ var params = ...