Trie tree实践
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实践的更多相关文章
- 字典树(Trie Tree)
终于要开始更新我的ACM学习之路了,不过没想到却是因为一次Java大作业,有趣,%yuan老师. 字典树是一种很简单的树形结构,主要用来进行词频统计,在算法竞赛中有时也会碰到. 字典树的基本思路是,通 ...
- 关于Trie Tree简单实现
最近突然有兴致hiho一下了,实现了下trie tree,感觉而言,还是挺有意思的,个人觉得这货不光可以用来查单词吧,其实也可以用来替代Hash,反正查找,插入复杂度都挺低的,哈哈,啥都不懂,瞎扯.. ...
- 笔试算法题(39):Trie树(Trie Tree or Prefix Tree)
议题:TRIE树 (Trie Tree or Prefix Tree): 分析: 又称字典树或者前缀树,一种用于快速检索的多叉树结构:英文字母的Trie树为26叉树,数字的Trie树为10叉树:All ...
- Phone List POJ 3630 Trie Tree 字典树
Phone List Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 29416 Accepted: 8774 Descr ...
- 字典树(Trie Tree)
在图示中,键标注在节点中,值标注在节点之下.每一个完整的英文单词对应一个特定的整数.Trie 可以看作是一个确定有限状态自动机,尽管边上的符号一般是隐含在分支的顺序中的.键不需要被显式地保存在节点中. ...
- hdu3724Encoded Barcodes(Trie tree)
题目请戳这里 题目大意:给n个字符串,给m个询问,每个询问给k个条形码.每个条形码由8个小码组成,每个小码有相应的宽度,已知一个条形码的宽度只有2种,宽的表示1,窄的表示0.并且宽的宽度是窄的宽度的2 ...
- trie tree(字典树)
hihocoder题目(http://hihocoder.com/problemset):#1014 trie树 #include <iostream> using namespace s ...
- Find the Clones Trie Tree
Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 8306 Accepted: 3130 Description Doubl ...
- 字典树Trie Tree
又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:利用字符串的公共前缀 ...
随机推荐
- Echarts 之三 —— 地市联动数据统计二
一.简介 除了是一个地图之外,我们也可以使用多地图进行地市.区县联动数据统计.需求如下:展示整改广东省的地图,并显示统计信息,当点击某一个地市的时候,就显示该地市的地图,并统计该地市区县的数据信息.二 ...
- 解决undefined reference to `__poll_chk@GLIBC_2.16' 错误
出现这个错误,是系统的glibc版本太低了,需要更新 到http://ftp.gnu.org/gnu/glibc/下载新版本的glibc,也不用太高,我选择glibc-2.20.tar.gz 解压 ...
- 使用 python 收集获取 Linux 系统主机信息
使用 python 代码收集主机的系统信息,主要:主机名称.IP.系统版本.服务器厂商.型号.序列号.CPU信息.内存等系统信息. #!/usr/bin/env python #encoding: u ...
- Ubuntu下Apache+SVN+submin实现WEB管理SVN
为什么需要submin管理SVN? 原来在Ubuntu下,都是直接通过命令行创建SVN仓库并分配权限,但是这有一些问题: 每创建一个SVN仓库,都需要修改httpd.conf 每创建一个帐户,都需要手 ...
- openwrt 安装 ser2net 配置
//--- openwrt中的ipk应用 opkg install /tmp/ser2net_2.7-2_brcm63xx.ipk 看到安装成功的信息后启动ser2net Ser2net –c /et ...
- 利用keepalived和haproxy配置mysql的高可用负载均衡
实验系统:CentOS 6.6_x86_64(2.6.32-504.30.3.el6.x86_64) 实验前提:防火墙和selinux都关闭 实验说明:本实验共有4台主机,IP分配如拓扑 实验软件:k ...
- MIT研发的新型匿名网络Riffle,下一个Tor
现在的隐私问题是一个网络热词,如果你担心你上网的隐私会泄露,最有效的解决办法就是使用Tor.这款免费的匿名通信软件,能够让人们在与其他人通信时隐藏自己真实的信息. 虽然Tor是一个很好的匿名网络系统, ...
- Spring远程调用技术<1>-RMI
在java中,我们有多种可以使用的远程调用技术 1.远程方法调用(remote method invocation, RMI) 适用场景:不考虑网络限制时(例如防火墙),访问/发布基于java的服务 ...
- Python的with用法理解
Python的with理解 标签(空格分隔): Python with做为一种上下文管理器,在Python中的作用可以简单的理解为是用来代替try...except...finally的处理流程. w ...
- java多线程系类:JUC线程池:04之线程池原理(三)(转)
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--"基础篇& ...