字典树
1. 基本知识
Trie树的基本性质可以归纳为:
- 根节点不包含字符,除根节点意外每个节点只包含一个字符。
- 从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。
- 每个节点的所有子节点包含的字符串不相同。
Trie树有一些特性:
1. 根节点不包含字符,除根节点外每一个节点都只包含一个字符。
2. 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
3. 每个节点的所有子节点包含的字符都不相同
4. 如果字符的种数为n,则每个结点的出度为n,这也是空间换时间的体现,浪费了很多的空间
5. 插入查找的复杂度为O(n),n为字符串长度。
2. 代码示例
//字典树的实现
struct TrieNode
{
TrieNode():exist(false)
{
memset(&next,0,sizeof(next));
}
//int count; //可以以此结点来对应的单词前缀的数量
bool exist; //记录是否是某个单词的尾部
TrieNode *next[26]; //记录子树的结点
};
class Trie {
public:
Trie()
{
root = new TrieNode();
}
//插入一个单词
void insert(string word) {
TrieNode *cur = root;
for(int i = 0; i < word.size();++i)
{
if(!(cur->next[word[i]-'a']) ) //为空,插入新的子树
{
cur->next[word[i]-'a'] = new TrieNode();
}
cur = cur->next[word[i]-'a'];
//++cur->count;
}
cur->exist = true;
}
//查询一个单词是否在字典树中
bool search(string word) {
if(word.empty())
return false;
TrieNode *cur = root;
for(int i = 0; i < word.size();++i)
{
if(!(cur->next[word[i]-'a'])) return false;
cur = cur->next[word[i]-'a'];
}
return cur->exist;
}
//查询以是否存在此前缀的单词
bool startsWith(string prefix) {
if(prefix.empty())
return false;
TrieNode *cur = root;
for(int i = 0; i < prefix.size();++i)
{
if(!(cur->next[prefix[i]-'a'])) return false;
cur = cur->next[prefix[i]-'a'];
}
return true;
}
private:
TrieNode *root;
};