Trie树/字典树
Trie树结构
Trie树是一种树形数据结构,又称为单词查找树、字典树,是一种用于快速检索的多叉树结构。典型应用是统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。
它的主要设计思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销。它的优点是可以最大限度的减少无谓的字符串比较,查询效率比哈希表高;缺点是内存消耗非常大。
Trie树基本特性
- 根节点不包含字符,除根节点外每一个节点都只包含一个字符
- 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串
- 每个节点的所有子节点包含的字符都不相同
Trie树的实现
1.插入过程
对于一个单词,从根开始,沿着单词的各个字母所对应的数中的节点分支向下走,直到单词遍历完,将最后的节点标记下来,表示是一个单词的结尾
插入单词(或者其他元素序列)过程中,需要对元素确定在“字典”中的序号,即hash。
2. 查找过程
(1)从根节点开始一次搜索;
(2)取得要查找关键字的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索;
(3)在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索;
(4)迭代....
(5)在某个节点处,关键词的所有字母都被取出,则读取附在节点上的信息,完成查找。
代码实现(c++)
#include<iostream> #include<string.h> using namespace std; #define MAX_CHILD_NUM 26 struct TrieNode{ int count; //用来标记以根为起点以该节点为终点的路径上经过的字符是否构成字典中的字符串 TrieNode* childs[MAX_CHILD_NUM]; TrieNode(){ count = 0; for (int i = 0; i < MAX_CHILD_NUM; i++){ childs[i] = NULL; } } }; void Insert(TrieNode* root, char* str){ if (root == NULL){ return; } TrieNode* node = root; char*p = str; while (*p != '\0'){ if (node->childs[*p - 'a'] == NULL){ node->childs[*p - 'a'] = new TrieNode(); } node = node->childs[*p - 'a']; p++; } node->count++; //以该节点为终点可以构成一个单词 } bool Search(TrieNode* root, char* str){ if (root == NULL){ return false; } TrieNode* node = root; char* p = str; while (*p != '\0'){ if (node->childs[*p - 'a'] == NULL){ break; } node = node->childs[*p - 'a']; p++; } if (*p == '\0' && node->count){ return true; } return false; } void Delete(TrieNode* node){ if (node == NULL){ return; } for (int i = 0; i < MAX_CHILD_NUM; i++){ Delete(node->childs[i]); } delete[] node->childs; } int main(){ TrieNode* root = new TrieNode(); char* strs[] = {"hello", "world", "how", "are", "you"}; for (auto s : strs){ Insert(root, s); } cout << Search(root, "how") << endl; cout << Search(root, "holy") << endl; return 0; }