字典树 trieTree
来源:互联网 发布:周笔畅淘宝店服装 编辑:程序博客网 时间:2024/06/16 17:56
Tire树
即字典树,又称单词查找树,利用字符串的公共前缀,省去很多重复的比较,从而节省查询时间。
经常被搜索引擎系统用于文本词频统计。
上图便是一颗字典树,
可以看到,该树有以下特点:
树的根节点不含字符,其余节点含且只含一个字符
兄弟间所含字符各不相同
红色表示在该点形成一个单词(从根节点到该节点路径上所有字符连成的字符串)
例如,abc、abcd、abd等都是单词,上图共有7个红色节点,故有7个单词。
ab并不是单词,只是某些单词的前缀。
假设我们要查询abc这个单词,首先要查询根节点的子节点中含不含a字符,如果不包含,则说明不包含abc这个单词。
如果根节点的子节点中包含a字符,那么我们只需从a节点开始查找,不必考虑第二层的b、e、h结点,如果a节点的子节点中不含b字符,则说明不包含abc这个单词,如果含b字符,则继续判断b字符的子节点中有没有c字符…
如果到了单词的最后一个字母,还需判断该节点“是否为红色”,如果是红色,则该字典树中存在这个单词。
可以看到,查询一个长度为n的单词,时间复杂度仅仅为O(n)。
至于字典树的构建,与查询的算法有些相仿。
例如,要在一颗字典树中插入单词efh,先看根节点的子节点中有没有e,如果没有,则为根节点创建一个子节点e,然后继续为e节点创建一个子节点f,然后……
如果根节点的子节点中有e,则继续看e节点的子节点中有没有f,无则创建,有则继续查询……
最后,插入或查询到最后一个字母,需把该节点“标志为红色”,表明在该节点形成一个单词。
#include<stdio.h>struct trieTree{ bool isstr; //isstr为true表明该节点处形成单词,也就是上文的“红色” trieTree* next[26]; //每个节点有26个子节点,不过还未赋“字符”};trieTree* _init(){//节点初始化 trieTree* r = new trieTree;//申请空间 r->isstr = false;//该节点不形成单词 for(int i=0;i<26;i++) r->next[i] = NULL;//为每个子节点赋值为空 return r;}void _insert(char* str,trieTree* root){//插入单词,str是待插入单词的首字母的地址 trieTree* tmp = root; while(*str!='\0'){//字符串的结束字符是'\0' if(!tmp->next[*str-'a']){ //next[i]中,i范围是0到25,分别代表字符a到z, //如果*str=b,那么next[*str-'a'], //即next[1],表示tmp节点的b子节点 //!tmp->next[*str-'a'] 指:tmp不存在b子节点 trieTree* r = _init();//创建结点 tmp->next[*str-'a'] = r; tmp = r; } else tmp = tmp->next[*str-'a']; //如果tmp存在(*str)节点,使tmp指向此节点 str++;//str指向下一个字母的地址 } tmp->isstr = true;//“标记为红色”}bool _search(char* str,trieTree* root){//查询单词,返回true表示待查询单词存在于字典树中,返回false表示不存在 trieTree* tmp = root; while(*str!='\0'){ if(!tmp->next[*str-'a']){ return false; //如果找不到(*str),说明字典树中不存在此单词,返回false } else tmp = tmp->next[*str-'a']; str++; } return tmp->isstr; //待查询单词的所有字母都找到了,还需判断最后一个单词结点是否为“红色”}void _del(trieTree* root){//释放内存 for(int i=0;i<26;i++) if(root->next[i]) _del(root->next[i]);//递归 delete root;}int main(){ trieTree* root = _init(); char str[4][10] = {"hello","world","software","engineer"}; for(int i=0;i<4;i++) _insert(str[i],root);//插入单词 char str1[10]; while(scanf("%s",str1),str1[0]!='#'){//输入'#'开头字符串结束输入 int ans = _search(str1,root); puts((ans?"yes":"no"));//如果ans==1输出yes,否则输出no } _del(root); return 0;}
当然,字典树的功能不止于查询某单词是否存在,经过适当修改,可以查询“以某字符串为前缀的单词个数”、“一组单词中某单词出现的次数”等。
- 字典树(TrieTree)
- leetcode208 字典树(TrieTree)
- 字典树 trieTree
- TrieTree字典树
- 字典树trietree Implement code
- Java实现字典树TrieTree
- POJ 3630 Phone List 静态字典树Trietree
- TrieTree字典树数据结构的原理、实现及应用
- TrieTree
- TrieTree(字典树,前缀树) 的实现 (增删改查)
- 递归TrieTree
- 傅老师课堂:TrieTree
- USACO prefix TrieTree + DP
- 非递归TrieTree
- TrieTree的实现
- 用java写的TrieTree
- 字典树
- 字典树
- InnoDB学习日记
- Codeforces #395 Div2
- 关于Shapefile乱码问题
- spring MVC HelloWord(xml)
- 小K的农场 洛谷1993 差分约束
- 字典树 trieTree
- js HTML5 Canvas绘制转盘抽奖
- 学习游戏服务器编程进阶篇之全球同服技术架构
- P1017 进制转换
- 常见的移动端和web的问题锦集
- sublime中有没有*.vue文件格式化插件?
- ActiveMq NON_PERSISTENT与PERSISTENT以及 durable subscription(持久订阅)的理解
- 【HDU3966】Aragorn's Story(树链剖分+线段树)
- 解决idea使用jstl标签报错和不自动提示