字典树查找原理

合集下载

Trie树&字典树的简介及实现

Trie树&字典树的简介及实现

Trie树/字典树的简介及实现Trie树|字典树的简介及实现1综述又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。

典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。

它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。

Trie树结构的优点在于:1)不限制子节点的数量;2)自定义的输入序列化,突破了具体语言、应用的限制,成为一个通用的框架;3)可以进行最大Tokens序列长度的限制;4)根据已定阈值输出重复的字符串;5)提供单个字符串频度查找功能;6)速度快,在两分钟内完成1998年1月份人民日报(19056行)的重复字符串抽取工作。

优点来源于Linux公社网站()/Linux/2012-04/57911.htm2性质它有3个基本性质:1) 根节点不包含字符,除根节点外每一个节点都只包含一个字符。

2) 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。

3) 每个节点的所有子节点包含的字符都不相同。

3基本操作其基本操作有:查找、插入和删除,当然删除操作比较少见.我在这里只是实现了对整个树的删除操作,至于单个word的删除操作也很简单.4实现方法搜索字典项目的方法为:(1) 从根结点开始一次搜索;(2) 取得要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索;(3) 在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索。

(4) 迭代过程……(5) 在某个结点处,关键词的所有字母已被取出,则读取附在该结点上的信息,即完成查找。

其他操作类似处理5. Trie原理——Trie的核心思想是空间换时间。

利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。

6.代码实现[cpp] view plaincopy1.const int branchNum = 26; //声明常量2.int i;3.4.struct Trie_node5.{6. boolisStr; //记录此处是否构成一个串。

字典树(Trie树)实现与应用

字典树(Trie树)实现与应用

字典树(Trie树)实现与应⽤⼀、概述 1、基本概念 字典树,⼜称为单词查找树,Tire数,是⼀种树形结构,它是⼀种哈希树的变种。

2、基本性质根节点不包含字符,除根节点外的每⼀个⼦节点都包含⼀个字符从根节点到某⼀节点。

路径上经过的字符连接起来,就是该节点对应的字符串每个节点的所有⼦节点包含的字符都不相同 3、应⽤场景 典型应⽤是⽤于统计,排序和保存⼤量的字符串(不仅限于字符串),经常被搜索引擎系统⽤于⽂本词频统计。

4、优点 利⽤字符串的公共前缀来减少查询时间,最⼤限度的减少⽆谓的字符串⽐较,查询效率⽐哈希树⾼。

⼆、构建过程 1、字典树节点定义class TrieNode // 字典树节点{private int num;// 有多少单词通过这个节点,即由根⾄该节点组成的字符串模式出现的次数private TrieNode[] son;// 所有的⼉⼦节点private boolean isEnd;// 是不是最后⼀个节点private char val;// 节点的值TrieNode(){num = 1;son = new TrieNode[SIZE];isEnd = false;}} 2、字典树构造函数Trie() // 初始化字典树{root = new TrieNode();} 3、建⽴字典树// 建⽴字典树public void insert(String str) // 在字典树中插⼊⼀个单词{if (str == null || str.length() == 0){return;}TrieNode node = root;char[] letters = str.toCharArray();//将⽬标单词转换为字符数组for (int i = 0, len = str.length(); i < len; i++){int pos = letters[i] - 'a';if (node.son[pos] == null) //如果当前节点的⼉⼦节点中没有该字符,则构建⼀个TrieNode并复值该字符{node.son[pos] = new TrieNode();node.son[pos].val = letters[i];}else//如果已经存在,则将由根⾄该⼉⼦节点组成的字符串模式出现的次数+1{node.son[pos].num++;}node = node.son[pos];}node.isEnd = true;} 4、在字典树中查找是否完全匹配⼀个指定的字符串// 在字典树中查找⼀个完全匹配的单词.public boolean has(String str){if(str==null||str.length()==0){return false;}TrieNode node=root;char[]letters=str.toCharArray();for(int i=0,len=str.length(); i<len; i++){int pos=letters[i]-'a';if(node.son[pos]!=null){node=node.son[pos];}else{return false;}}//⾛到这⼀步,表明可能完全匹配,也可能部分匹配,如果最后⼀个字符节点为末端节点,则是完全匹配,否则是部分匹配return node.isEnd;} 5、前序遍历字典树 // 前序遍历字典树.public void preTraverse(TrieNode node){if(node!=null){System.out.print(node.val+"-");for(TrieNode child:node.son){preTraverse(child);}}} 6、计算单词前缀的数量 // 计算单词前缀的数量public int countPrefix(String prefix){if(prefix==null||prefix.length()==0){return-1;}TrieNode node=root;char[]letters=prefix.toCharArray();for(int i=0,len=prefix.length(); i<len; i++){int pos=letters[i]-'a';if(node.son[pos]==null){return 0;}elsenode=node.son[pos];}}return node.num;} 完整代码:package com.xj.test;public class Trie{private int SIZE = 26;private TrieNode root;// 字典树的根class TrieNode // 字典树节点{private int num;// 有多少单词通过这个节点,即由根⾄该节点组成的字符串模式出现的次数private TrieNode[] son;// 所有的⼉⼦节点private boolean isEnd;// 是不是最后⼀个节点private char val;// 节点的值TrieNode(){num = 1;son = new TrieNode[SIZE];isEnd = false;}}Trie() // 初始化字典树{root = new TrieNode();}// 建⽴字典树public void insert(String str) // 在字典树中插⼊⼀个单词{if (str == null || str.length() == 0){return;}TrieNode node = root;char[] letters = str.toCharArray();//将⽬标单词转换为字符数组for (int i = 0, len = str.length(); i < len; i++){int pos = letters[i] - 'a';if (node.son[pos] == null) //如果当前节点的⼉⼦节点中没有该字符,则构建⼀个TrieNode并复值该字符 {node.son[pos] = new TrieNode();node.son[pos].val = letters[i];}else//如果已经存在,则将由根⾄该⼉⼦节点组成的字符串模式出现的次数+1{node.son[pos].num++;}node = node.son[pos];}node.isEnd = true;}// 计算单词前缀的数量public int countPrefix(String prefix){if(prefix==null||prefix.length()==0){return-1;}TrieNode node=root;char[]letters=prefix.toCharArray();for(int i=0,len=prefix.length(); i<len; i++){int pos=letters[i]-'a';if(node.son[pos]==null){return 0;}else{node=node.son[pos];}return node.num;}// 打印指定前缀的单词public String hasPrefix(String prefix){if (prefix == null || prefix.length() == 0){return null;}TrieNode node = root;char[] letters = prefix.toCharArray();for (int i = 0, len = prefix.length(); i < len; i++){int pos = letters[i] - 'a';if (node.son[pos] == null){return null;}else{node = node.son[pos];}}preTraverse(node, prefix);return null;}// 遍历经过此节点的单词.public void preTraverse(TrieNode node, String prefix){if (!node.isEnd){for (TrieNode child : node.son){if (child != null){preTraverse(child, prefix + child.val);}}return;}System.out.println(prefix);}// 在字典树中查找⼀个完全匹配的单词.public boolean has(String str){if(str==null||str.length()==0){return false;}TrieNode node=root;char[]letters=str.toCharArray();for(int i=0,len=str.length(); i<len; i++){int pos=letters[i]-'a';if(node.son[pos]!=null){node=node.son[pos];}else{return false;}}//⾛到这⼀步,表明可能完全匹配,可能部分匹配,如果最后⼀个字符节点为末端节点,则是完全匹配,否则是部分匹配return node.isEnd;}// 前序遍历字典树.public void preTraverse(TrieNode node){if(node!=null){System.out.print(node.val+"-");for(TrieNode child:node.son){preTraverse(child);}}}public TrieNode getRoot(){return this.root;}public static void main(String[]args){Trie tree=new Trie();String[]strs= {"banana","band","bee","absolute","acm",};String[]prefix= {"ba","b","band","abc",};for(String str:strs){tree.insert(str);}System.out.println(tree.has("abc"));tree.preTraverse(tree.getRoot());System.out.println();//tree.printAllWords();for(String pre:prefix){int num=tree.countPrefix(pre);System.out.println(pre+"数量:"+num);}}}View Code 执⾏结果截图:三、简单应⽤ 下⾯讲⼀个简单的应⽤,问题是这样的: 现在有⼀个英⽂字典(每个单词都是由⼩写的a-z组成),单词量很⼤,⽽且还有很多重复的单词。

理解字典树算法的主要特点

理解字典树算法的主要特点

理解字典树算法的主要特点字典树(Trie树)是一种高效的数据结构,用于存储和搜索字符串集合。

它的主要特点是能够快速地进行字符串的插入、删除和搜索操作。

在本文中,我们将深入探讨字典树算法的主要特点。

一、前缀匹配字典树的主要特点之一是能够实现高效的前缀匹配。

它通过将字符串按照字符逐层存储在树的节点上,从而构建了一种前缀索引结构。

在搜索时,只需按照要匹配的前缀逐个字符地遍历字典树的节点,直到找到匹配的节点或遍历完整个字符串。

这种前缀匹配的方式使得字典树在搜索引擎、自动补全等场景中具有广泛的应用。

二、空间优化字典树的另一个重要特点是能够对空间进行优化。

由于字典树中存在大量的重复前缀,可以通过共享相同前缀的节点来减少存储空间的使用。

这种共享节点的方式称为压缩字典树(压缩前缀树或Patricia树)。

通过将多个相同前缀的节点合并为一个节点,可以大大减少字典树的存储空间,提高性能。

三、高效的插入和删除操作字典树的插入和删除操作非常高效。

在插入字符串时,只需按照字符逐层遍历字典树的节点,并在需要时创建新的节点。

同样,在删除字符串时,只需将对应的节点标记为删除状态即可。

这种基于节点的操作方式使得插入和删除操作的时间复杂度为O(m),其中m为字符串的长度。

四、适用于大规模数据集字典树算法适用于处理大规模的字符串数据集。

由于字典树的前缀匹配特性,它可以快速地定位到匹配的字符串,而不需要遍历整个数据集。

这使得字典树在处理大规模数据集时具有较高的效率和性能。

五、多种应用领域字典树算法在多个应用领域都有广泛的应用。

在文本编辑器中,字典树可用于实现拼写检查和自动补全功能。

在网络路由中,字典树可用于快速匹配IP地址。

在模式匹配中,字典树可用于搜索字符串中的特定模式。

此外,字典树还可以用于构建索引、词频统计等。

六、复杂度分析字典树的时间复杂度主要取决于字符串的长度和字典树的高度。

在最坏情况下,字典树的高度等于字符串的最大长度,因此插入、删除和搜索操作的时间复杂度为O(m),其中m为字符串的长度。

字典树高效的字符串检索工具

字典树高效的字符串检索工具

字典树高效的字符串检索工具字典树,也称为前缀树或Trie树,是一种常用的数据结构,用于快速检索字符串。

它能够有效地解决字符串查找的问题,特别适用于大量字符串的存储与检索。

本文将介绍字典树的结构、功能以及应用场景,以展示字典树作为高效的字符串检索工具的优势。

一、字典树的结构和基本功能字典树是一种多叉树,其中每个节点包含一个字符,节点之间通过指针连接。

根节点不包含字符,每个节点除了存储字符外,还有一个布尔变量用来标记该节点是否为某个字符串的结束位置。

通过从根节点开始沿着指针路径不断遍历,可以得到完整的字符串。

字典树具有以下基本功能:1. 字符串的插入:将一个字符串插入到字典树中,从根节点开始,逐级查找该字符串是否已经存在对应节点,若存在则不进行插入,若不存在则创建新节点,并将对应字符插入到新节点中。

2. 字符串的搜索:从根节点开始,逐级查找目标字符串,若能够找到完整字符串,则返回true,否则返回false。

3. 字符串的前缀搜索:从根节点开始,逐级查找目标字符串的前缀,若能够找到,则返回true,否则返回false。

二、字典树的应用场景字典树在各种应用中都有广泛的应用,下面列举几个常见的应用场景来展示其高效的字符串检索能力。

1. 搜索引擎关键词提示:搜索引擎可以利用字典树快速地根据用户的输入进行关键词提示,通过构建字典树,将所有关键词存储在树中,用户每输入一个字符,就通过字典树进行搜索,给出可能的关键词提示,提高搜索的效率和准确性。

2. 单词拼写检查:字典树可以用来进行单词拼写的检查。

用户输入一个单词后,可以通过字典树进行匹配,若匹配成功则表示单词正确,若匹配失败则表示单词拼写错误,并给出可能的正确单词建议。

3. 模式匹配:字典树可以用来进行模式匹配,例如在一个文本中查找多个关键词。

通过将所有关键词构建成字典树,然后从文本起始位置开始,逐个字符在字典树中进行搜索,若能够找到完整的关键词,则表示匹配成功。

trie树原理

trie树原理

trie树原理trie树,又称字典树或前缀树,是一种用于高效存储和检索字符串的数据结构。

它的原理是利用字符串的公共前缀来减少存储空间和搜索时间。

trie树的基本结构是一个根节点,每个节点包含一个字符和若干子节点。

根节点不包含字符,每个子节点代表一个字符。

从根节点到叶子节点的路径上的字符连接起来就是一个完整的字符串。

每个节点还可以存储额外的信息,如出现次数、权重等。

trie树的构建过程是逐个插入字符串。

从根节点开始,根据字符串的每个字符依次向下遍历。

如果当前字符对应的子节点不存在,则创建一个新的子节点,并将当前字符插入到子节点中。

如果当前字符对应的子节点已存在,则直接向下遍历。

重复这个过程,直到字符串的所有字符都被插入到trie树中。

trie树的搜索过程也是从根节点开始,根据待搜索的字符依次向下遍历。

如果当前字符对应的子节点存在,则继续向下遍历。

如果当前字符对应的子节点不存在,则表示trie树中不存在该字符串,搜索失败。

当搜索到字符串的最后一个字符时,可以根据需要返回节点的额外信息,如出现次数、权重等。

trie树的优点是可以高效地存储和检索大量的字符串。

由于trie树利用了字符串的公共前缀,相同前缀的字符串共享相同的节点,大大减少了存储空间。

同时,trie树的搜索时间复杂度与待搜索字符串的长度无关,只与trie树中存储的字符串数量有关,平均情况下为O(k),其中k为字符串的平均长度。

trie树的应用非常广泛。

在文本编辑器中,可以利用trie树实现自动补全、拼写检查等功能。

在搜索引擎中,可以利用trie树实现关键词的快速匹配。

在网络路由中,可以利用trie树实现IP地址的快速查找。

在字典等应用中,可以利用trie树实现单词的快速检索。

然而,trie树也存在一些缺点。

首先,trie树的构建过程比较耗时,需要遍历所有的字符串。

其次,trie树的存储空间较大,对于大量长字符串的存储可能会占用较多的内存。

最后,trie树的节点数量可能会很大,导致内存访问不连续,降低了缓存的效果。

字典树在文本搜索中的关键词匹配

字典树在文本搜索中的关键词匹配

字典树在文本搜索中的关键词匹配字典树,也被称为前缀树或Trie树,是一种高效的数据结构,用于字符串的存储和搜索。

字典树在文本搜索中的关键词匹配起到了重要的作用。

本文将探讨字典树在关键词匹配中的应用及其优势。

一、什么是字典树字典树是一种类似于树的数据结构,它有助于快速地搜索和存储字符串。

字典树是由节点构成的,节点中存储了一个字符,节点之间通过指针连接。

根节点是空节点,每个节点的子节点可能包含26个英文字母,对应于26个字典顺序表。

二、字典树的构建1. 构建字典树的首要任务是向树中插入关键词。

假设我们要插入一个关键词"apple",首先从根节点开始,查找第一个字符"a"的位置。

如果该位置已经存在节点,则直接转到该节点,否则创建一个新节点。

接下来,继续查找下一个字符"p"的位置,如果不存在节点,则创建一个新节点,以此类推,直到关键词的最后一个字符插入完毕。

2. 当我们需要搜索一个关键词时,从根节点开始,依次查找关键词中的每个字符。

如果某个字符在当前节点的子节点中存在,则继续向下查找,否则停止搜索,表示关键词不存在。

三、字典树的关键词匹配字典树在文本搜索中的关键词匹配非常高效。

假设我们有一个文本数据集,包含多个关键词,我们需要判断这些关键词是否在某个文本中出现。

1. 构建字典树:首先,我们需要将这些关键词插入到字典树中,构建一棵完整的字典树。

2. 关键词匹配:对于待搜索的文本,从左到右逐个字符进行匹配。

首先从根节点开始,在字典树中查找第一个字符的位置,如果存在,则继续向下匹配,否则停止匹配。

在匹配过程中,如果遇到一个节点标记为关键词结束,则表示匹配成功。

3. 多关键词匹配:字典树可以高效地支持多关键词匹配。

对于待搜索的文本,我们依次判断其中的每一个字符,然后在字典树中进行匹配。

如果匹配成功,则可以得到匹配到的关键词,继续匹配下一个字符,直到文本中的所有字符匹配完毕。

字典树算法——精选推荐

字典树算法⼀,思想试想⼀下,你查⼀个单词⽐如说book,那么你在字典中,先翻到b开头的部分,在翻到b这⼀段o开始的部分,依次类推,直到找到book这个单词,如果你不⼩⼼看错了⼀个字母,⽐如book你看成了boak,那么显然你查找到字母a后,查找不下去了,或者是查找到错误的单词,字典树,就是描述的上述过程。

举个栗⼦:六个单词:an,am,and,math,mac,ok那么字典树如下:每个单词结束时给个标记,⽐如下⾯画⼀个短横线。

⼆,⽤途字符串索引,查找。

统计单词个数(只需要在单词结束标记处增加⼀个计数即可)。

前缀匹配,这个很像linux下命令⼀样,你只需要输⼊前⾯⼏个字母,按tab键即可补全命令。

字符串排序(按照字典顺序插⼊,前序遍历字典树即可)。

三,复杂度暴⼒匹配复杂度:逐个匹配复杂度为O(mn),m为字符串平均长度。

字典树,插⼊和查找都时O(m),m为插⼊字典树的单词的长度。

四,实现树结构来实现#include <iostream>#include <string.h>using namespace std;struct Trie{Trie* next[26]; // ⼀个节点只会出现26个字母26种情况int num; // 记录以当前字符串为前缀的单词数量Trie(){for(int i = 0; i < 26; i++)next[i] = NULL;num = 0;}};Trie root; // 根节点void Insert(char str[]){// 将字符串插⼊字典树中Trie *p = &root;for(int i = 0; str[i]; i++){if(p->next[str[i]-'a'] == NULL){ // 如果当前字符没有对应的节点则创建⼀个p->next[str[i]-'a'] = new Trie; // 创建⼀个新的节点}p = p->next[str[i]-'a'];p -> num++;}}int Find(char str[]){// 查找以str为前缀的单词数量Trie *p = &root;for(int i = 0; str[i]; i++){ // 从第⼀个字母开始从顶向下依次查找if(p->next[str[i]-'a'] == NULL){ // 如果当前节点没有这个单词中的当前位置的字母则查找失败return 0;}p = p->next[str[i]-'a'];}return p->num; // 返回当前单词结尾处的前缀数量}数组实现(更紧凑的代码)int trie[10005][26]; // 数组定义字典树,存储下⼀个字符的位置int num[10005] = {0}; // 统计某⼀个字符串为前缀的数量int pos = 1; // 当前新分配的存储位置void Insert(char str[]){int p = 0;for(int i = 0; str[i]; i++){int n = str[i] - 'a';if(trie[p][n] == 0){ // 当前节点没有值trie[p][n] = pos++; // 为了在num数组中更好的记录前缀出现的次序}p = trie[p][n];num[p] ++;}}int Find(char str[]){int p = 0;for(int i = 0; str[i]; i++){int n = str[i] - 'a';if(trie[p][n] == 0){return 0;}p = trie[p][n];}return num[p];}五,应⽤查找⼀组单词中,以某个词为前缀的单词有多少个int main(){char str[11];while(gets(str)){if(!strlen(str)) break; // 输⼊空⾏则跳出去Insert(str);}while(gets(str)) cout << Find(str) <<endl;return 0;}输出结果:amandokmathmac // 输⼊结束ma2a2and1c注:当然解决该问题,map为⼀个不错的⽅法,只需定义map<string, int> m 将单词插⼊时,只需要m[str]++即可。

基数树查找原理

基数树查找原理
基数树(Radix Tree),也称为字典树(Trie),是一种常用于高效存储和检索字符串的数据结构。

它的设计理念是基于字符串的特性,将字符串的每个字符作为节点进行存储和检索。

基数树的查找原理是通过将要存储或检索的字符串拆分为单个字符,并将每个字符作为节点插入到树中。

树的根节点代表空字符,每个节点包含一个字符和一个指向子节点的指针数组。

在进行插入操作时,将要插入的字符串从左到右逐个字符地与树中的节点进行比较。

若节点为空,则创建一个新节点并连接到父节点的对应子节点指针上;若节点不为空,则继续比较下一个字符。

插入完成后,将字符串的最后一个字符所对应的节点标记为终止节点,表示该字符串的结束。

在进行查找操作时,同样从根节点开始,逐个字符与节点进行比较。

若节点为空,则表示该字符串不存在于树中,查找失败;若节点不为空,则继续比较下一个字符。

当达到字符串的最后一个字符时,如果对应的节点为终止节点,则表示该字符串存在于树中,查找成功;否则查找失败。

基数树的优势是在存储和检索字符串时具有较高的效率。

由于它的特性是按照字符进行存储和检索,所以对于相同前缀的字符串,它们共享相同的前缀节点,节省了空间。

同时,基数树也支持高效的前缀匹配,可以快速地找到具有相同前缀的字符串。

总结起来,基数树是一种通过将字符串拆分为单个字符并按照字符序列构建树的数据结构。

它的查找原理是通过比较字符串的每个字符与树中的节点进行匹配,直到字符串结束或遇到终止节点。

基数树在存储和检索字符串方面具有高效性和前缀匹配的优势。

字典(Trie)树:如何实现搜索引擎的搜索关键词提示功能?

字典(Trie)树:如何实现搜索引擎的搜索关键词提⽰功能? Trie 树,也叫“字典树”。

顾名思义,它是⼀个树形结构。

它是⼀种专门处理字符串匹配的数据结构,⽤来解决在⼀组字符串集合中快速查找某个字符串的问题。

它并不是⼆叉树,⽽是“多叉树”。

class TrieNode {char data;TrieNode children[26];} 刚刚我们在讲 Trie 树的实现的时候,讲到⽤数组来存储⼀个节点的⼦节点的指针。

如果字符串中包含从 a 到 z 这 26 个字符,那每个节点都要存储⼀个长度为 26 的数组,并且每个数组元素要存储⼀个 8 字节指针(或者是 4 字节,这个⼤⼩跟 CPU、操作系统、编译器等有关)。

⽽且,即便⼀个节点只有很少的⼦节点,远⼩于 26 个,⽐如 3、4 个,我们也要维护⼀个长度为 26 的数组。

我们前⾯讲过,Trie 树的本质是避免重复存储⼀组字符串的相同前缀⼦串,但是现在每个字符(对应⼀个节点)的存储远远⼤于 1 个字节。

按照我们上⾯举的例⼦,数组长度为 26,每个元素是 8 字节,那每个节点就会额外需要 26*8=208 个字节。

⽽且这还是只包含 26 个字符的情况。

如果字符串中不仅包含⼩写字母,还包含⼤写字母、数字、甚⾄是中⽂,那需要的存储空间就更多了。

所以,也就是说,在某些情况下,Trie 树不⼀定会节省存储空间。

在重复的前缀并不多的情况下,Trie 树不但不能节省内存,还有可能会浪费更多的内存。

当然,我们不可否认,Trie 树尽管有可能很浪费内存,但是确实⾮常⾼效。

那为了解决这个内存问题,我们是否有其他办法呢? 我们可以稍微牺牲⼀点查询的效率,将每个节点中的数组换成其他数据结构,来存储⼀个节点的⼦节点指针。

⽤哪种数据结构呢?我们的选择其实有很多,⽐如有序数组、跳表、散列表、红⿊树等。

实际上,字符串的匹配问题,笼统上讲,其实就是数据的查找问题。

对于⽀持动态数据⾼效操作的数据结构,我们前⾯已经讲过好多了,⽐如散列表、红⿊树、跳表等等。

字典树(前缀树)的实现

字典树(前缀树)的实现在实现字典树(前缀树)之前,我们先看⼀下什么是字典树(前缀树)“字典树⼜称前缀树,Trie树,是⼀种树形结构,是⼀种哈希树的变种。

典型应⽤是⽤于统计,排序和保存⼤量的字符串(但不仅限于字符串),所以经常被搜索引擎系统⽤于⽂本词频统计。

它的优点是:利⽤字符串的公共前缀来减少查询时间,最⼤限度地减少⽆谓的字符串⽐较,查询效率⽐哈希树⾼。

”------百度百科字典树是⼀种树形结构,优点是利⽤字符串的公共前缀来节约存储空间。

字典树如图1所⽰:图1在字典树上搜索添加过的单词的步骤如下:1、从根结点开始搜索2、取得要查找单词的第⼀个字母,并根据该字母选择对应的字符路径向下继续搜索。

3、字符路径指向的第⼆层节点上,根据第⼆个字母选择对应的字符路径向下继续搜索。

4、⼀直向下搜索,如果单词搜索完后,找到的最后⼀个节点是⼀个终⽌节点,⽐如图1中的实⼼节点,说明字典树中含有这个单词,如果找到的最后⼀个节点不是⼀个终⽌节点,说明单词不是字典树中添加过的单词。

如果单词没搜索完,但是已经没有后续的节点了,也说明单词不是字典树中添加过的单词。

题⽬:字典树(前缀树)的实现:字典树⼜称为前缀树或Trie树,是处理字符串常见的数据结构。

假设组成所有单词的字符串是“a”~“z”,请实现字典树结构,并包含以下四个主要功能。

void insert(String word):添加word,可以重复添加。

void delete(String word):删除word,如果word添加过多次,仅删除⼀个。

boolean search(String word):查询word是否在字典树中。

int prefixNumber(String pre):返回以字符串pre为前缀的单词数量。

1class TrieNode {2int path;3int end;4 TrieNode[] map;56 TrieNode() {7 path=0;8 end=0;9 map=new TrieNode[26];10 }11 }12class Trie {13private TrieNode root;14public Trie() {15 root=new TrieNode();16 }17public void insert(String word) {18if (word==null) {19return;20 }21char[] chs=word.toCharArray();22 TrieNode node=root;23 node.path++;24int index=0;25for (int i=0; i<chs.length; i++) {26 index=chs[i]-'a';27if (node.map[index]==null) {28 node.map[index]=new TrieNode();29 }30 node=node.map[index];31 node.path++;32 }33 node.end++;34 }35public void delete(String word) {36if (search(word)) {37char[] chs=word.toCharArray();38 TrieNode node=root;39 node.path--;40int index=0;41for (int i=0; i<chs.length; i++) {42 index=chs[i]-'a';43 node.map[index].path--;44 node=node.map[index];45 }46 node.end--;47 }48 }49public boolean search(String word) {50if (word==null) {51return false;52 }53char[] chs=word.toCharArray();54 TrieNode node=root;55int index=0;56for (int i=0; i<chs.length; i++) {57 index=chs[i]-'a';58if (node.map[index]==null) {59return false;60 }61 node=node.map[index];62 }63return node.end!=0;64 }65public int prefixNumber(String pre) {66if (pre==null) {67return 0;68 }69char[] chs=pre.toCharArray();70 TrieNode node=root;71int index=0;72for (int i=0; i<chs.length; i++) {73 index=chs[i]-'a';74if (node.map[index]==null) {75return 0;76 }77 node=node.map[index];78 }79return node.path;80 }81 }LeetCode208实现Trie(前缀树)题⽬描述:实现⼀个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

字典树查找原理
字典树(Trie树),又称前缀树或键树,是一种用于高效存储和查找字符串的数据结构。

它的查找原理基于字符串的公共前缀,可以在O(m)的时间复杂度内查找到字符串,其中m是字符串的长度。

字典树的基本结构是一个有根的树,每个节点包含若干个指向子节点的指针。

通常,一个节点对应一个字符,从根节点开始,根据字符串的每个字符依次向下遍历,直到到达字符串的最后一个字符或无法继续向下遍历为止。

字典树的插入操作是将字符串的每个字符依次插入到树中。

如果字符对应的子节点不存在,则创建一个新的节点,并将该节点与父节点连接。

重复这个过程,直到插入完整个字符串。

最后,将最后一个字符的节点标记为字符串的结束。

字典树的查找操作是从根节点开始,依次比较每个字符,根据字符找到对应的子节点,直到到达字符串的最后一个字符或无法继续向下遍历为止。

如果到达字符串的最后一个字符且该节点被标记为字符串的结束,说明字符串存在于字典树中;否则,字符串不存在。

字典树的优点是能够高效地存储和查找字符串。

它利用了字符串的公共前缀,可以大大减少存储空间和查找时间。

在字典树中,相同前缀的字符串共享相同的节点,因此可以节省存储空间。

而查找操作只需要依次比较每个字符,时间复杂度为O(m),其中m是字符
串的长度,与字典树中字符串的数量无关。

字典树还可以用于前缀匹配。

通过查找某个前缀节点的子节点,可以找到以该前缀开头的所有字符串。

这在自动补全、搜索引擎和拼写检查等应用中非常有用。

然而,字典树的缺点是消耗大量的内存。

由于每个节点都需要存储指向子节点的指针,如果字符串的字符集很大,那么字典树将变得非常庞大。

此外,在构建字典树的过程中,需要频繁地动态分配内存,这可能导致内存碎片化。

为了解决字典树的内存消耗问题,可以使用压缩字典树(压缩前缀树)。

压缩字典树将只有一个子节点的节点进行合并,从而减少了存储空间。

同时,压缩字典树的查找操作也会稍微复杂一些,需要遍历字符串的每个字符,并判断是否需要跳过合并的节点。

除了基本的插入和查找操作,字典树还可以支持删除操作。

删除操作需要删除字符串的最后一个字符节点,并递归删除其父节点,直到父节点不再有其他子节点为止。

字典树是一种高效存储和查找字符串的数据结构。

它利用了字符串的公共前缀,可以节省存储空间和查找时间。

然而,字典树的内存消耗较大,可以通过压缩字典树进行改进。

字典树在自动补全、搜索引擎和拼写检查等领域有着广泛的应用。

通过合理地使用字典树,
可以提高字符串的存储和查找效率,提升程序的性能。

相关文档
最新文档