数据之美之Trie树
原博客地址:http://blog.csdn.net/nash_/article/details/8227610
Trie树(又叫字典树,前缀树,单词查找树,键树)是一种树形数据结构,直接来看图:
我们来看看Trie树的特点:根节点为空值,剩下每一个节点保存一个字母。知道这些就够了!
我们再来看看这棵树能干什么?如果从根节点遍历到某一个节点把路径节点的值连在一起就构成了一个字符串,利用这个特点很容易想到这棵树的第一个功能能帮我们查找某一个单词是否在树中(需要在每一个节点设置一个标志,表示从根节点到此节点是否构成一个单词);如果该单词存在,我们可以利用它实现第二个功能:去除重复单词;同样如果该词存,在我们还可以看出它的第三个功能:统计单词频率;因为这是一个树形结构我们利用这个特点很容易看出它的第四个功能能帮我们查找N个单词的最长公共前缀;如果我们按顺序遍历输出整棵树,发现它的第五个功能:对字符串排序。
这棵树创建看起来比较容易,就有一个问题需要我们考虑:父节点如何保存孩子节点? 主要有两种方式供大家参考:
1.因为是英文字符,我们可以用Node[26]来保存孩子节点(如果是数字我们可以用Node[10]),这种方式最快,但是并不是所有节点都会有很多孩子,所以这种方式浪费的空间太多
2.用一个链表根据需要动态添加节点。这样我们就可以省下不小的空间,但是缺点是搜索的时候需要遍历这个链表,增加了时间复杂度。
下面我用数组保存孩子节点的方式实现的trie树:
- class TrieNode{//结点类
- private static final int NUMBER = 26;
- private char _value;
- private boolean _isWord;//从根节点到这个节点存不存在一个单词
- TrieNode[] _children = new TrieNode[NUMBER];//子结点集合
- public TrieNode(char c) {
- this.setValue(c);
- }
- public char getValue() {
- return _value;
- }
- public void setValue(char _value) {
- this._value = _value;
- }
- public boolean isWord() {
- return _isWord;
- }
- public void setIsWord(boolean _isWord) {
- this._isWord = _isWord;
- }
- }
- public class TrieTree {
- static String[] _words = {"add","am","good","the","think"};//待插入单词
- private boolean searchWord(TrieNode _root, String _word) {
- if(null == _root || null == _word || "".equals(_word))
- return false;
- char[] cs = _word.toCharArray();//将字符串转化为字符数组
- for(int i = 0; i < cs.length; i++){
- int index;
- if(cs[i] >= 'A' && cs[i] <= 'Z'){
- index = cs[i]-'A';
- }
- else if(cs[i] >= 'a' && cs[i] <= 'z')
- index = cs[i] - 'a';
- else
- return false;
- TrieNode child_node = _root._children[index];
- if(null != child_node){//找到相同字符
- if(child_node.isWord())//如果找到该单词
- return true;
- }
- if(null == child_node)//如果在i层没找到相同字符
- return false;
- _root = child_node;//重设根节点
- }
- return false;
- }
- private void insertIntoTree(TrieNode _root, String _word) {//插入一个单词
- if(null == _root || null == _word || "".equals(_word))
- return;
- char[] cs = _word.toCharArray();//将字符串转化为字符数组
- for(int i = 0; i < cs.length; i++){
- int index;//对应的索引值
- if(cs[i] >= 'A' && cs[i] <= 'Z'){
- index = cs[i]-'A';
- }
- else if(cs[i] >= 'a' && cs[i] <= 'z')
- index = cs[i] - 'a';
- else
- return;
- TrieNode child_node = _root._children[index];
- if(null == child_node){//如果没找到
- TrieNode new_node = new TrieNode(cs[i]);//创建新节点
- if(i == cs.length-1)//如果遍历到该单词最后一个字符
- new_node.setIsWord(true);//把该单词存在树中
- _root._children[index] = new_node;//连接该节点
- _root = new_node;
- }else
- _root = child_node;//更新树根
- }
- }
- private void printTree(TrieNode _root,char[] _word,int index) {
- if(_root == null)
- return;
- if(_root.isWord()){//如果根节点到此节点构成一个单词则输出
- for(char c : _word){
- if(c != ' ')
- System.out.print(c);
- }
- System.out.println();
- }
- for(TrieNode node : _root._children){//遍历树根孩子节点
- if(node != null){//回溯法遍历该树
- _word[index++] = node.getValue();
- printTree(node,_word,index);
- _word[index] = ' ';
- index--;
- }
- }
- }
- public static void main(String[] args){
- TrieTree _tree = new TrieTree();//创建一棵树
- TrieNode _root = new TrieNode(' ');//创建根节点
- for(String word : _words)//插入单词
- _tree.insertIntoTree(_root,word);
- char[] _word = new char[20];
- _tree.printTree(_root,_word,0);//打印树中单词
- boolean status = _tree.searchWord(_root,"think");//查询树中是否存在某单词
- System.out.println(status);
- }
- }
class TrieNode{//结点类
private static final int NUMBER = 26;
private char _value;
private boolean _isWord;//从根节点到这个节点存不存在一个单词
TrieNode[] _children = new TrieNode[NUMBER];//子结点集合
public TrieNode(char c) {
this.setValue(c);
}
public char getValue() {
return _value;
}
public void setValue(char _value) {
this._value = _value;
}
public boolean isWord() {
return _isWord;
}
public void setIsWord(boolean _isWord) {
this._isWord = _isWord;
}
}
public class TrieTree {
static String[] _words = {"add","am","good","the","think"};//待插入单词
private boolean searchWord(TrieNode _root, String _word) {
if(null == _root || null == _word || "".equals(_word))
return false;
char[] cs = _word.toCharArray();//将字符串转化为字符数组
for(int i = 0; i < cs.length; i++){
int index;
if(cs[i] >= 'A' && cs[i] <= 'Z'){
index = cs[i]-'A';
}
else if(cs[i] >= 'a' && cs[i] <= 'z')
index = cs[i] - 'a';
else
return false;
TrieNode child_node = _root._children[index];
if(null != child_node){//找到相同字符
if(child_node.isWord())//如果找到该单词
return true;
}
if(null == child_node)//如果在i层没找到相同字符
return false;
_root = child_node;//重设根节点
}
return false;
}
private void insertIntoTree(TrieNode _root, String _word) {//插入一个单词
if(null == _root || null == _word || "".equals(_word))
return;
char[] cs = _word.toCharArray();//将字符串转化为字符数组
for(int i = 0; i < cs.length; i++){
int index;//对应的索引值
if(cs[i] >= 'A' && cs[i] <= 'Z'){
index = cs[i]-'A';
}
else if(cs[i] >= 'a' && cs[i] <= 'z')
index = cs[i] - 'a';
else
return;
TrieNode child_node = _root._children[index];
if(null == child_node){//如果没找到
TrieNode new_node = new TrieNode(cs[i]);//创建新节点
if(i == cs.length-1)//如果遍历到该单词最后一个字符
new_node.setIsWord(true);//把该单词存在树中
_root._children[index] = new_node;//连接该节点
_root = new_node;
}else
_root = child_node;//更新树根
}
}
private void printTree(TrieNode _root,char[] _word,int index) {
if(_root == null)
return;
if(_root.isWord()){//如果根节点到此节点构成一个单词则输出
for(char c : _word){
if(c != ' ')
System.out.print(c);
}
System.out.println();
}
for(TrieNode node : _root._children){//遍历树根孩子节点
if(node != null){//回溯法遍历该树
_word[index++] = node.getValue();
printTree(node,_word,index);
_word[index] = ' ';
index--;
}
}
}
public static void main(String[] args){
TrieTree _tree = new TrieTree();//创建一棵树
TrieNode _root = new TrieNode(' ');//创建根节点
for(String word : _words)//插入单词
_tree.insertIntoTree(_root,word);
char[] _word = new char[20];
_tree.printTree(_root,_word,0);//打印树中单词
boolean status = _tree.searchWord(_root,"think");//查询树中是否存在某单词
System.out.println(status);
}
}
==================================================================================================
数据之美之Trie树相关推荐
- ┎结构之美┒之Trie树
博主今天新开一系列写"结构",简单的单链表,普通队列,普通栈,普通二叉树就不写了,今天从Trie树写起. Trie树(又叫字典树,前缀树,单词查找树,键树)是一种树形数据结构,直接 ...
- Trie树 c++实现
1. Trie树介绍 Trie,又称单词查找树.前缀树,是一种多叉树结构.如下图所示: 上图是一棵Trie树,表示了关键字集合{"a", "to", " ...
- 算法学习之Trie树
算法学习之Trie树 by MPS [定义] trie树又名字母树,是针对字符串的匹配,查找的一种高效手段,是哈希表的一种变种,但青出于蓝胜于蓝.我这个蒟蒻也是表示啃了两天才啃出来这些皮毛,当做学 ...
- mysql索引用trie树_数据结构与算法之美【完整版】
资源目录: ├─01-开篇词 (1讲) │ ├─00丨开篇词丨从今天起,跨过"数据结构与算法"这道坎.html │ ├─00丨开篇词丨从今天起,跨过"数据结构与算法&qu ...
- 数据结构与算法之美笔记——基础篇(下):图、字符串匹配算法(BF 算法和 RK 算法、BM 算法和 KMP 算法 、Trie 树和 AC 自动机)
图 如何存储微博.微信等社交网络中的好友关系?图.实际上,涉及图的算法有很多,也非常复杂,比如图的搜索.最短路径.最小生成树.二分图等等.我们今天聚焦在图存储这一方面,后面会分好几节来依次讲解图相关的 ...
- 【BZOJ3217】ALOEXT-暴力重构线段树-替罪羊树-Trie树-树套树-10k大代码(+数据生成器)...
Problem ALOEXT 题目大意 给出一个数据结构维护一个数列,要求支持以下操作: 向数列中某个位置插入一个数 将数列中某个位置的数删除 将数列中某个位置的数换成另外一个数 查询一段区间内的次大 ...
- LeetCode 211. 添加与搜索单词 - 数据结构设计(Trie树)
1. 题目 设计一个支持以下两种操作的数据结构: void addWord(word) bool search(word) search(word) 可以搜索文字或正则表达式字符串,字符串只包含字母 ...
- c语言 trie树,数据结构篇——字典树(trie树)
引入 现在有这样一个问题, 给出$n$个单词和$m$个询问,每次询问一个单词,回答这个单词是否在单词表中出现过. 好像还行,用 map ,几行就完事了. 那如果n的范围是 $10^5$ 呢?再用 $m ...
- Trie 树——搜索关键词提示
当你在搜索引擎中输入想要搜索的一部分内容时,搜索引擎就会自动弹出下拉框,里面是各种关键词提示,这个功能是怎么实现的呢?其实底层最基本的就是 Trie 树这种数据结构. 1. 什么是 "Tri ...
最新文章
- 坡道行驶电动小车_事发红绿灯路口!东莞一女子骑电动滑板车被撞致颅内出血…...
- Java HashMap原理及内部存储结构
- yolo 标注转VOC格式(标注转换器)
- TDSQL 全时态数据库系统-理念与愿景
- Boost-QT兼容问题:#define FUSION_HASH #
- day52 Django全流程
- 学习opencv之cvtColor
- Nginx反向代理、动静分离、负载均衡及rewrite隐藏路径详解(Nginx Apache MySQL Redis)–第二部分...
- MySQL之一篇读懂binlog redolog undolog
- 15_Python模块化编程_Python编程之路
- java设置请求头_前端需要知道的 HTTP 安全头配置
- SPSS学习(二)作图
- 20172301 《程序设计与数据结构》第六周学习总结
- 如何高效开展测试用例评审?附用例评审检查清单及用例评审报告模板
- 我的世界java版动作优化_我的世界动作优化模组
- 烟台气象台发布蓝色预警信号: 今日大到暴雪
- 三相电网的共模与差模
- DC入门(一)综合基础
- 如何区别API、REST API、RESTful API和Web Service之间的异同
- 英语作文计算机国际会议开幕词,有关英语会议开场致辞范文
热门文章
- python实现阴阳师自动刷御魂脚本_Python实现阴阳师电脑端自动组队刷御魂
- 【总结】有三AI重要原创人脸相关的技术文章汇总(2022年8月)
- 视频美颜sdk中人脸识别的主要实现流程
- java drawimage 缩放_java drawImage 如何实现旋转和缩放
- MLK | Keras 核心网络层的解读指南
- HTTP 401 错误 - 未授权 终极解决办法
- @Select标签内的大于小于判断符号
- 读懂系列 | 10个例子带你了解机器学习中的线性代数
- c语言-字符串放入字符数组
- linux sd卡修复工具,如何使用'fsck'修复Linux中的文件系统错误