- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
第
C++前缀树字典树的学习与模拟实现代码示例
目录前缀树介绍C++实现核心思想前缀树的大致框架前缀树插入字符串前缀树查找完整的字符串前缀树查找前缀匹配的字符串前缀树删除完整字符串总结完整代码
前缀树介绍
在计算机科学中,trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。常用与拼写检查自动补全等;是一种查找结构他的存储逻辑类似于哈希表,但是它相对于哈希表来说,限制更多,通用性较差,但是它的功能更加强大,可定制性也更强。leetcode指路:实现Trie(前缀树)
如图可以查看trie树的基本结构:
与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。(这个是前缀树的精髓,也是难理解的地方,他不用存储某个节点的实际字符,他的对应下标映射出了需要存储的字符!)
一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。
一般情况下,不是所有的节点都有对应的值(他们只是前缀),只有叶子节点和部分内部节点所对应的键才有相关的值。
C++实现
核心思想
单链表:通过Node中封装的Node*next来找下一个连着的节点;
二叉树:通过Node中封装的Node*left和Node*right来找左右孩子节点;
前缀树?
因为维护了26个可能的Node*节点,所以跟上面一个道理,只是不能枚举出来了,用了一个Node*arr[26]来维护,恰巧把这个数组的下标设计成了某个字符的种类,就可以达到利用逻辑下标存储一个实际字符的作用了!
前缀树插入示意图
上图中,每经过一个节点,将该节点的pass值加一,将末尾节点的end值加一。通过这种操作记录所有经过的数据记录
前缀树的插入是灵魂所在,搞懂了之后结构就明白了,不管是查找还是删除无非就是类似对链表的相关操作;
前缀树的大致框架
假设只存小写字符:
#includeiostream
#includevector
#includestring
usingnamespacestd;
//26个小写英文字母
#defineNUM26
classTrie{
private:
Trie*arr[NUM];//多叉树(最大26个分支,因为26个小写字母嘛)
intend;//代表word完整单词的个数,0就是无此单词,只是一个前缀;insert一个单词的时候,这个单词的end首次出现就置为1;之后重复插入就end++;
intpass;//代表以此前缀为公共前缀的节点个数,每次insert的时候会调整;
public:
Trie(){
memset(arr,0,sizeof(arr));//每个新节点的映射数组内容置nullptr
end=0;
ncount=0;//初始化时以该映射信息字符为前缀的个数为1(这个字符本身算的1)
//插入单词
voidInsert(stringx)
//查找完全匹配字符串x的数量
intFind(stringx)
//查找前缀为字符串x的数量
intFindContain(stringx)
//删除某个单词(前缀)
boolErase(stringx)
~Trie()
//因为new了26个连续的tire*空间,不要某个节点,不要把它对应给下层准备的26个空间也delete掉防止内存泄漏
for(inti=0;iNUMBER;i++)
if(nexts[i]){
deletenexts[i];
};
二叉树,父节点之下包含两个节点,分别为左右子节点,分别开辟空间,进行数据存储。前缀树的结构也是类似的,它的每个节点包含两个部分:值部分和指针部分。它的存储方式为:在一棵树上,从根到子节点,分别存储所有目标数据的每一个下标位置上的数据值部分主要又包含两个数据:路过该节点的数量为pass,以该节点为结尾的数量为end。指针部分主要包含它的所有子节点(比如26个小写字母),记为arr
下面的实现给出了四个接口:
Insert插入字符串,给前缀树添加一组数据
其中Insert方法需要注意插入新单词的过程中,路径所有前缀的个数pass+1
Find查找已存入的完整匹配的字符串个数FindContain查找已存入的前缀匹配的字符串个数Erase从前缀树中擦除一个完整字符串
Erase方法需要注意的是:
需Find先检查
文档评论(0)