一 概述

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

二 优点

利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。

三 性质

(1)根节点不包含字符,除根节点外每一个节点都只包含一个字符;
(2)从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串;
(3)每个节点的所有子节点包含的字符都不相同。

单词列表为”apps”,”apply”,”apple”,”append”,”back”,”backen”以及”basic”对应的字母树可以是如下图所示。

例如,保存”apple”和 “apply”时,由于它们的前四个字母是相同的,所以希望它们共享这些字母,而只对剩下的部分进行分开存储。可以很明显地发现,字母树很好地利用了串的公共前缀,节约了存储空间。

四 应用

(1)串的快速检索

给出N个单词组成的熟词表,以及一篇全用小写英文书写的文章,请你按最早出现的顺序写出所有不在熟词表中的生词。
在这道题中,我们可以用数组枚举,用哈希,用字典树,先把熟词建一棵树,然后读入文章进行比较,这种方法效率是比较高的。

(2)“串”排序

给定N个互不相同的仅由一个单词构成的英文名,让你将他们按字典序从小到大输出用字典树进行排序,采用数组的方式创建字典树,这棵树的每个结点的所有儿子很显然地按照其字母大小排序。对这棵树进行先序遍历即可。

(3)最长公共前缀

对所有串建立字典树,对于两个串的最长公共前缀的长度即他们所在的结点的公共祖先个数,于是,问题就转化为当时公共祖先问题。

五 实现

字典树的插入(Insert)、删除( Delete)和查找(Find )都非常简单,用一个一重循环即可,即第 i 次循环找到前 i 个字母所对应的子树,然后进行相应的操作。实现这棵字典树,我们用最常见的数组保存即可,当然也可以开动态的指针类型。至于结点对儿子的指向,一般有三种方法:
(1)对每个结点开一个字母集大小的数组,对应的下标是儿子所表示的字母,内容则是这个儿子对应在大数组上的位置,即标号;
(2)对每个结点挂一个链表,按一定顺序记录每个儿子是谁;
(3)使用左儿子右兄弟表示法记录这棵树。
三种方法,各有千秋。第一种易实现,但实际的空间要求较大;第二种,
较易实现,空间要求相对较小,但比较费时;第三种,空间要求最小,但相对费时且不易写。但总的来说,几种实现方式都是比较简单的,只要在做题时加以合理选择即可。

/*---------------------------------------------
*   日期:2015-02-21
*   作者:SJF0115
*   题目: 20.字典树
*   来源:算法系列
*   博客:
-----------------------------------------------*/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;#define MAX 26struct TrieNode{// 以该节点为结尾的单词个数int count;TrieNode *next[MAX];TrieNode(int x):count(x){for(int i = 0;i < MAX;++i){next[i] = NULL;}//for}
};
// 插入
void Insert(TrieNode* &root,string str){int size = str.size();int val;TrieNode *p = root;// 一个一个字符插入for(int i = 0;i < size;++i){val = str[i] - 'a';// 之前没有该字符if(p->next[val] == NULL){p->next[val] = new TrieNode(0);}//ifp = p->next[val];}//for// 以该字符为结尾p->count++;
}
// 删除
void Delete(TrieNode* &root,string str){int size = str.size();int val;TrieNode *p = root;// 一个一个字符插入for(int i = 0;i < size;++i){val = str[i] - 'a';// 删除的字符串不在字典中if(p->next[val] == NULL){return;}//ifp = p->next[val];}//for// 以该字符为结尾p->count--;
}
// 查找
bool Search(TrieNode* root,string str){if(root == NULL){return false;}//ifint size = str.size();TrieNode *p = root;int val;for(int i = 0;i < size;++i){val = str[i] - 'a';// 无法转移到下一个字符if(p->next[val] == NULL){return false;}//if// 继续下一个字符p = p->next[val];}//forreturn p->count > 0;
}
// 打印字典
void PrintDic(TrieNode* root,vector<vector<char> > &words,vector<char> &word){if(root == NULL){return;}//ifif(root->count > 0){words.push_back(word);}//iffor(int i = 0;i < 26;++i){if(root->next[i]){word.push_back('a'+i);PrintDic(root->next[i],words,word);word.pop_back();}//if}//for
}int main() {TrieNode* root = new TrieNode(0);// 插入string strs[] = {"ok","applition","app","apple","apply"};for(int i = 0;i < 5;++i){Insert(root,strs[i]);}//forstring str("apple");cout<<"删除单词["<<str<<"]之前查询结果:"<<endl;// 查询if(Search(root,str)){cout<<"单词["<<str<<"]在字典中"<<endl;}//ifelse{cout<<"单词["<<str<<"]不在字典中"<<endl;}cout<<"删除单词["<<str<<"]"<<endl;// 删除Delete(root,str);cout<<"删除单词["<<str<<"]之后查询结果:"<<endl;// 查询if(Search(root,str)){cout<<"单词["<<str<<"]在字典中"<<endl;}//ifelse{cout<<"单词["<<str<<"]不在字典中"<<endl;}// 字典列表cout<<"字典列表:"<<endl;vector<vector<char> > words;vector<char> word;PrintDic(root,words,word);for(int i = 0;i < words.size();++i){for(int j = 0;j < words[i].size();++j){cout<<words[i][j];}//forcout<<endl;}//forreturn 0;
}

六 引用

字典树Trie

算法合集之《浅析字母树在信息学竞赛中的应用》

从Trie树(字典树)谈到后缀树(10.28修订)

有问题欢迎指正,谢谢。。。。。。。

[算法系列之二十]字典树(Trie)相关推荐

  1. 机器学习算法系列(二十二)-近似k近邻算法-Annoy(Approximate Nearest Neighbor / ANN)

    阅读本文需要的背景知识点:k近邻算法.一丢丢编程知识 一.引言   前面一节我们学习了机器学习算法系列(二十一)-k近邻算法(k-Nearest Neighbor / kNN Algorithm),其 ...

  2. 算法系列之二十:计算中国农历(二)

    (接上篇) 所谓的"天文算法",就是利用经典力学定律推导行星运转轨道,对任意时刻的行星位置进行精确计算,从而获得某种天文现象发生时的时间,比如日月合朔这一天文现象就是太阳和月亮的地 ...

  3. [算法系列之二十六]字符串匹配之KMP算法

    一 简介 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特-莫里斯-普拉特操作(简称KMP算法).KMP算法的关键是利 ...

  4. 算法系列之二十:计算中国农历(一)

    世界各国的日历都是以天为最小单位,但是关于年和月的算法却各不相同,大致可以分为三类: 阳历--以天文年作为日历的主要周期,例如:中国公历(格里历) 阴历--以天文月作为日历的主要周期,例如:伊斯兰历 ...

  5. 机器学习算法系列(二十)-梯度提升决策树算法(Gradient Boosted Decision Trees / GBDT)

    阅读本文需要的背景知识点:自适应增强算法.泰勒公式.One-Hot编码.一丢丢编程知识 一.引言   前面一节我们学习了自适应增强算法(Adaptive Boosting / AdaBoost Alg ...

  6. 快乐学算法之:字典树Trie

    文章目录 简介 Trie的特性 Trie树和Hashing,BST的对比 Trie树的程序化表示 Trie树的插入 Trie树的搜索 Trie树的删除 Trie树的疑惑 简介 字典树的英文名叫做Tri ...

  7. 用Python实现字典树(Trie)与双数组字典树(DATrie)

    1. 字典树(Trie) 假如我们把字典中的词以记录的形式(无序)存入数据库中.现给定一串字符,要查找该字符串是否为字典中的词.因为数据库中的记录是无序的,所以,最朴素的方法就逐记录匹配.此方法简单, ...

  8. 强化学习系列文章(二十八):进化强化学习EvoRL的预实验

    强化学习系列文章(二十八):进化强化学习EvoRL的预实验 最近在研究强化学习解决离散空间的组合优化问题时,接触到了很多进化算法,实际体验也是与RL算法不相上下.进化算法也常用于优化神经网络的参数,C ...

  9. 精通八大排序算法系列:二、堆排序算法

    精通八大排序算法系列:二.堆排序算法 作者:July .二零一一年二月二十日 本文参考:Introduction To Algorithms,second edition. ------------- ...

最新文章

  1. 柱形图无数据可选中_这种漂亮的“连体”柱形图,99%的人不会做!
  2. DDOS学习笔记(《破坏之王-DDOS攻击与防范深度剖析》)
  3. redis(10)--RDB持久化
  4. blender教学记录
  5. Java生产环境下性能监控与调优详解 大纲 学习感悟
  6. 比尔·盖茨退出微软公司董事会;苹果 WWDC、微软 Build 大会均改为线上举办;Rust 1.42.0 发布| 极客头条...
  7. C#中的类型转换(转载)
  8. matlab 数值计算方法 pdf,《现代数值计算方法(MATLAB版)》习题解答.pdf
  9. 2022年计算机软件水平考试网络管理员(初级)练习题及答案
  10. 【IJCAI 2022】参数高效的大模型稀疏训练方法,大幅减少稀疏训练所需资源
  11. 安装office 错误代码:30068-39
  12. CrystalDiskInfo 各项参数说明
  13. 【工业互联网】漫谈“工业互联网”与“智能制造”
  14. 猜数字(超级简单题目)
  15. Python+uiautomtor2实现app自动化测试
  16. 版本管理-SVN分支,合并,切换
  17. 并查集(Union-Find) (图文详解)
  18. 服务器硬件基础设施,【通讯技术】细节定成败,NFV中的硬件基础设施管理
  19. 挂载zookeeper到文件系统 (mount zookeeper)
  20. C语言从键盘上输入年份和月份,计算并输出这一年的这一月共有多少天。

热门文章

  1. php反射型xss,利用反射型XSS漏洞,模拟获取登录账户的Cookie
  2. MPI并行计算学习笔记6——行主元高斯消去法
  3. kubernetes-nvidia-plugin设计解读
  4. Could not acquire hardware tool communications resources: ICD3PlatformTool SN#
  5. 【教学类-22-02】20221210《八款字体的描字帖-4*4格整张-不用订书机》(大班主题《我是中国人-中国字》)
  6. GCJ-02火星坐标系、BD-09百度坐标系和WGS-84坐标系转换
  7. 张量分解——CP分解与Tucker分解详解
  8. 9.19上海交大PMP每日一题
  9. macOS从Mojave更新到Catalina之后无法联网的问题
  10. PPT中如何插入SWF视频文件(百分之百有效的方法)