diff --git a/4 Tree/4-字典树Trie/README.md b/4 Tree/4-字典树Trie/README.md index e69de29..cda44ef 100644 --- a/4 Tree/4-字典树Trie/README.md +++ b/4 Tree/4-字典树Trie/README.md @@ -0,0 +1,152 @@ +# 字典树trie + +## trie基本 + +`字典树`,英文名`Trie树`,Trie一词来自retrieve,发音为/tri:/ “tree”,也有人读为/traɪ/ “try”, +又称`单词查找树` 或 `前缀树`,Trie树,是一种树形结构(多叉树)。 + +trie,又称为前缀树或字典树,是一种有序树,用于保存关联数组。 + +1. 除根节点不包含字符,每个节点都包含一个字符 +2. 从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串 +3. 每个节点的所有子节点包含的字符都不相同(保证每个节点对应的字符串都不一样) + +比如: + +``` + / \ + / | \ + t a i + / \ \ + o e n + /|\ / + a d n n +``` + +上面的Trie树,可以表示字符串集合{“a”, “to”, “tea”, “ted”, “ten”, “i”, “in”, “inn”} 。 + +trie树把每个关键字保存在一条路径上,而不是一个节点中 +两个有公共前缀的关键字,在Trie树中前缀部分的路径相同,所以Trie树又叫做前缀树(Prefix Tree)。 + + + +### trie 优缺点 + +它的优点是: + +1. 插入和查询的效率很高,都是O(m),其中 m 是待插入/查询的字符串的长度 +2. Trie树可以对关键字按字典序排序 +3. 利用字符串的公共前缀来最大限度地减少无谓的字符串比较,提高查询效率 + +缺点: + +1. trie 树比较费内存空间,在处理大数据时会内存吃紧 +2. 当hash函数较好时,Hash查询效率比 trie 更优 + +[知乎这里](http://www.zhihu.com/question/27168319)有个问题:`10万个串找给定的串是否存在`, 对trie和hash两种方案给出了讨论。 + + +[DATrie](https://github.com/kmike/datrie) 是使用python实现的双数组trie树, 双数组可以减少内存的使用量 。有关 double-array trie,可以参考[这篇论文](http://linux.thai.net/~thep/datrie/datrie.html) + + +### trie应用 + +典型应用是:前缀查询,字符串查询,排序 + +* 用于统计,排序和保存大量的字符串(但不仅限于字符串) +* 经常被搜索引擎系统用于文本词频统计 +* 排序大量字符串 +* 用于索引结构 +* 敏感词过滤 + + +### 实际应用问题 + +1. 给你100000个长度不超过10的单词。对于每一个单词,我们要判断他出没出现过,如果出现了,求第一次出现在第几个位置 +分析思路一:trie树 ,找到这个字符串查询操作就可以了,如何知道出现的第一个位置呢?我们可以在trie树中加一个字段来记录当前字符串第一次出现的位置。 + +2. 已知n个由小写字母构成的平均长度为10的单词,判断其中是否存在某个串为另一个串的前缀子串 + +3. 给出N 个单词组成的熟词表,以及一篇全用小写英文书写的文章,请你按最早出现的顺序写出所有不在熟词表中的生词。 +分析:trie树查询单词的应用。先建立N个熟词的前缀树,然后按文章的单词一次查询。 + +4. 给出一个词典,其中的单词为不良单词。单词均为小写字母。再给出一段文本,文本的每一行也由小写字母构成。判断文本中是否含有任何不良单词。例如,若rob是不良单词,那么文本problem含有不良单词。 +分析:先用不良单词建立trie树,然后过滤文本(每个单词都在trie树上查询,查询的复杂度O(1),效率非常高),这正是`敏感词过滤系统(或垃圾评论系统)`的原理。 + +5. 给你N 个互不相同的仅由一个单词构成的英文名,让你将它们按字典序从小到大排序输出 +分析:这是trie树排序的典型应用,建立N个单词的trie树,然后线序遍历整个树,就可以达到效果。 + + + + +## trie树存储结构和基本操作 + +最简单实现 ---- 26个字母表 a-z (没有考虑数字,大小写,其他字符如=-*/) +子树用数组存储,浪费空间;如果系统中存在大量字符串,且这些字符串基本没有公共前缀,trie树将消耗大量内存 +如果用链表存储,查询时需要遍历链表,查询效率有所降低 + + + +``` +define ALPHABET_NUM 26 +typedef struct trie_node{ + char value; + bool isKey;/*是否代表一个关键字*/ + int count; /*可用于词频统计,表示关键字出现的次数*/ + struct Node *subTries[ALPHABET]; +}*Trie + +Trie Trie_create(); +int Trie_insert(Trie trie,char *word); // 插入一个单词 +int Trie_search(Trie trie,char *word);// 查找一个单词 +int Trie_delete(Trie trie,char *word);// 删除一个单词 + +Trie Trie_create(){ + trie_node* pNode = new trie_node(); + pNode->count = 0; + for(int i=0; ichildren[i] = NULL; + return pNode; +} + +void trie_insert(trie root, char* key) +{ + trie_node* node = root; + char* p = key; + while(*p) + { + if(node->children[*p-'a'] == NULL) + { + node->children[*p-'a'] = create_trie_node(); + } + node = node->children[*p-'a']; + ++p; + } + node->count += 1; +} + +/** + * 查询:不存在返回0,存在返回出现的次数 + */ +int trie_search(trie root, char* key) +{ + trie_node* node = root; + char* p = key; + while(*p && node!=NULL) + { + node = node->children[*p-'a']; + ++p; + } + + if(node == NULL) + return 0; + else + return node->count; +} + +``` + +trie树的增加和删除都比较麻烦,但索引本身就是写少读多,是否考虑添加删除的复杂度上升,依靠具体场景决定。 + + + diff --git a/4 Tree/4-字典树Trie/字典树.md b/4 Tree/4-字典树Trie/字典树.md deleted file mode 100644 index 5a33c3a..0000000 --- a/4 Tree/4-字典树Trie/字典树.md +++ /dev/null @@ -1,148 +0,0 @@ - - -## 字典树trie - -### trie基本 - -`字典树`,英文名`Trie树`,Trie一词来自retrieve,发音为/tri:/ “tree”,也有人读为/traɪ/ “try”, -又称`单词查找树` 或 `前缀树`,Trie树,是一种树形结构(多叉树)。 - -trie,又称为前缀树或字典树,是一种有序树,用于保存关联数组。 - -1. 除根节点不包含字符,每个节点都包含一个字符 -2. 从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串 -3. 每个节点的所有子节点包含的字符都不相同(保证每个节点对应的字符串都不一样) - -比如: - -``` - / \ - / | \ - t a i - / \ \ - o e n - /|\ / - a d n n -``` - -上面的Trie树,可以表示字符串集合{“a”, “to”, “tea”, “ted”, “ten”, “i”, “in”, “inn”} 。 - -trie树把每个关键字保存在一条路径上,而不是一个节点中 -两个有公共前缀的关键字,在Trie树中前缀部分的路径相同,所以Trie树又叫做前缀树(Prefix Tree)。 - - -### trie树存储结构和基本操作 - -最简单实现 ---- 26个字母表 a-z (没有考虑数字,大小写,其他字符如=-*/) -子树用数组存储,浪费空间;如果系统中存在大量字符串,且这些字符串基本没有公共前缀,trie树将消耗大量内存 -如果用链表存储,查询时需要遍历链表,查询效率有所降低 - - - -``` -define ALPHABET_NUM 26 -typedef struct trie_node{ - char value; - bool isKey;/*是否代表一个关键字*/ - int count; /*可用于词频统计,表示关键字出现的次数*/ - struct Node *subTries[ALPHABET]; -}*Trie - -Trie Trie_create(); -int Trie_insert(Trie trie,char *word); // 插入一个单词 -int Trie_search(Trie trie,char *word);// 查找一个单词 -int Trie_delete(Trie trie,char *word);// 删除一个单词 - -Trie Trie_create(){ - trie_node* pNode = new trie_node(); - pNode->count = 0; - for(int i=0; ichildren[i] = NULL; - return pNode; -} - -void trie_insert(trie root, char* key) -{ - trie_node* node = root; - char* p = key; - while(*p) - { - if(node->children[*p-'a'] == NULL) - { - node->children[*p-'a'] = create_trie_node(); - } - node = node->children[*p-'a']; - ++p; - } - node->count += 1; -} - -/** - * 查询:不存在返回0,存在返回出现的次数 - */ -int trie_search(trie root, char* key) -{ - trie_node* node = root; - char* p = key; - while(*p && node!=NULL) - { - node = node->children[*p-'a']; - ++p; - } - - if(node == NULL) - return 0; - else - return node->count; -} - -``` - -trie树的增加和删除都比较麻烦,但索引本身就是写少读多,是否考虑添加删除的复杂度上升,依靠具体场景决定。 - - -### trie 问题 - -它的优点是: - -1. 插入和查询的效率很高,都是O(m),其中 m 是待插入/查询的字符串的长度 -2. Trie树可以对关键字按字典序排序 -3. 利用字符串的公共前缀来最大限度地减少无谓的字符串比较,提高查询效率 - -缺点: - -1. trie 树比较费内存空间,在处理大数据时会内存吃紧 -2. 当hash函数较好时,Hash查询效率比 trie 更优 - -[知乎这里](http://www.zhihu.com/question/27168319)有个问题:`10万个串找给定的串是否存在`, 对trie和hash两种方案给出了讨论。 - - -[DATrie](https://github.com/kmike/datrie) 是使用python实现的双数组trie树, 双数组可以减少内存的使用量 。有关 double-array trie,可以参考[这篇论文](http://linux.thai.net/~thep/datrie/datrie.html) - - -### trie应用 - -典型应用是:前缀查询,字符串查询,排序 - -* 用于统计,排序和保存大量的字符串(但不仅限于字符串) -* 经常被搜索引擎系统用于文本词频统计 -* 排序大量字符串 -* 用于索引结构 -* 敏感词过滤 - -### 实际应用问题 - -1. 给你100000个长度不超过10的单词。对于每一个单词,我们要判断他出没出现过,如果出现了,求第一次出现在第几个位置 -分析思路一:trie树 ,找到这个字符串查询操作就可以了,如何知道出现的第一个位置呢?我们可以在trie树中加一个字段来记录当前字符串第一次出现的位置。 - -2. 已知n个由小写字母构成的平均长度为10的单词,判断其中是否存在某个串为另一个串的前缀子串 - -3. 给出N 个单词组成的熟词表,以及一篇全用小写英文书写的文章,请你按最早出现的顺序写出所有不在熟词表中的生词。 -分析:trie树查询单词的应用。先建立N个熟词的前缀树,然后按文章的单词一次查询。 - -4. 给出一个词典,其中的单词为不良单词。单词均为小写字母。再给出一段文本,文本的每一行也由小写字母构成。判断文本中是否含有任何不良单词。例如,若rob是不良单词,那么文本problem含有不良单词。 -分析:先用不良单词建立trie树,然后过滤文本(每个单词都在trie树上查询,查询的复杂度O(1),效率非常高),这正是`敏感词过滤系统(或垃圾评论系统)`的原理。 - -5. 给你N 个互不相同的仅由一个单词构成的英文名,让你将它们按字典序从小到大排序输出 -分析:这是trie树排序的典型应用,建立N个单词的trie树,然后线序遍历整个树,就可以达到效果。 - diff --git a/4 Tree/5-伸展数/伸展树.md b/4 Tree/5-伸展树/伸展树.md similarity index 100% rename from 4 Tree/5-伸展数/伸展树.md rename to 4 Tree/5-伸展树/伸展树.md diff --git a/4 Tree/6-后缀数/后缀树.md b/4 Tree/6-后缀树/后缀树.md similarity index 100% rename from 4 Tree/6-后缀数/后缀树.md rename to 4 Tree/6-后缀树/后缀树.md diff --git a/4 Tree/7-B数/B+树.md b/4 Tree/7-B树/B+树.md similarity index 100% rename from 4 Tree/7-B数/B+树.md rename to 4 Tree/7-B树/B+树.md diff --git a/4 Tree/7-B数/B树.md b/4 Tree/7-B树/B树.md similarity index 100% rename from 4 Tree/7-B数/B树.md rename to 4 Tree/7-B树/B树.md diff --git a/4 Tree/8-二叉堆(优先队列)/heap.c b/4 Tree/8-堆/heap.c similarity index 100% rename from 4 Tree/8-二叉堆(优先队列)/heap.c rename to 4 Tree/8-堆/heap.c diff --git a/4 Tree/8-二叉堆(优先队列)/大顶堆 和 小顶堆.md b/4 Tree/8-堆/堆.md similarity index 100% rename from 4 Tree/8-二叉堆(优先队列)/大顶堆 和 小顶堆.md rename to 4 Tree/8-堆/堆.md diff --git a/4 Tree/9-红黑树 R-B tree/红黑树.md b/4 Tree/9-红黑树 R-B tree/红黑树.md index 054a499..c537fcd 100644 --- a/4 Tree/9-红黑树 R-B tree/红黑树.md +++ b/4 Tree/9-红黑树 R-B tree/红黑树.md @@ -4,7 +4,7 @@ ### 应用场景 java 中 HashMap、TreeMap 的底层实现,当HashMap中元素大于8个时,HashMap底层存储实现改为红黑树,以提高元素搜索速度。 -关于 HashMap 实现解析参考 [这里](.../Hash\ Table/HashMap\ in\ Java.md) +关于 HashMap 实现解析参考 [这里](../../3%20HashTable/HashMap%20in%20Java.md) diff --git a/4 Tree/README.md b/4 Tree/README.md index 96bd546..977ba8a 100644 --- a/4 Tree/README.md +++ b/4 Tree/README.md @@ -1,20 +1,51 @@ - -## 树🌲 +# 树🌲 介绍树相关的算法 +* 二叉树 * 二叉查找树 -* 赫夫曼编码 Huffman +* AVL树 * 字典树trie(前缀树,单词查找树) * 伸展树 * 后缀树 -* AVL树 +* B树 : B树, B+树(mysql索引使用B+树的数据结构) +* 红黑树 +* 二叉堆(优先队列) * 红黑树 -* B树 -* B+树 mysql索引使用B+树的数据结构 -* B*树 -* R树 * Treap 树 +* 赫夫曼编码 Huffman + + +## [二叉查找树](2-二叉查找树/二叉查找树.md) + + +## [AVL树](3-平衡树AVL/README.md) + + +## [字典树trie](4-字典树Trie/README.md) + +字典树也叫前缀树,单词查找树 + + +## [伸展树](5-伸展树/伸展树.md) + + +## [后缀树](6-后缀树/后缀树.md) + +## B树 + +* [B树](7-B树/B树.md) +* [B+树](7-B树/B+树.md) mysql 索引使用 B+树 的数据结构 + + +## [二叉堆](8-堆/堆.md) + + +## [红黑树](9-红黑树%20R-B%20tree/红黑树.md) + + +## 赫夫曼编码 Huffman +