一、Trie 树是我一直想看却一直拖着没看的数据结构。主要应用的思想是通过构建树结构,使得前缀相同的字符串可共享前缀序列,一旦构建好树结构后,便可实现快速检索。
适用场景:1)找到所有前缀相同的字符串 2)以字典序枚举数据集中的每个字符串。
哈希表在上述两种场景下会有大量的哈希碰撞(hash collisions)且搜索的时间复杂度很高(最差情形下为 O(n),n为插入的键值数)。故相较于哈希表,Trie可通过存储相同前缀的字符串节省更多的空间,故搜索的时间复杂度仅为O(m), m为键长(即字符串长度)
二、主要的应用有:构建字典(查询某个单词是否在字典中)、自动纠正语法错误、自动补齐单词、IP地址路由选择等。
1)根节点的特点:
1. Trie为有根树,根节点为空,不表示任何字符
2. 每个节点最多有R个孩子(若字符串中每个字符取值为‘a’~‘z’,则R=26),第i个孩子表示字母表中的第i个字符
2)插入元素
依次遍历字符串中的每个元素,若该元素存在,继续遍历下一元素;否则,插入一新的节点。
3)查找某字符串是否存在
与2)类似,依次遍历字符串中的每个元素,若该元素存在,继续遍历下一元素;否则,返回false。
例题:LeetCode 208. Implement Trie
代码如下:
class TrieNode{
public:
char var; //该节点对应的字符
bool isword; //标记从根节点到该节点是否表示一个单词或另一单词的前缀
TrieNode* child[26]; //子节点用一个数组表示,实现简单但耗内存
// Initialize the data structure
TrieNode()
{
var = 0;
isword = false;
memset(child, 0, sizeof(child));
}
TrieNode(char c)
{
var = c;
isword = false;
memset(child, 0, sizeof(child));
}
};
class Trie {
public:
/** Initialize your data structure here. */
Trie() {
root = new TrieNode();
}
/** Inserts a word into the trie. */
void insert(string word) {
if(word.length()<=0) return;
TrieNode *pNode = root;
for(int i=0; i<word.length(); ++i)
{
char c = word[i];
if(pNode->child[c-'a'] == 0)
{
TrieNode *pNew = new TrieNode(c);
pNode->child[c-'a'] = pNew;
}
pNode = pNode->child[c-'a'];
}
pNode->isword = true;
}
/** Returns if the word is in the trie. */
bool search(string word) {
TrieNode *pNode = root;
if(word.length()<=0) return true;
for(int i=0; i<word.length(); ++i)
{
char c = word[i];
pNode = pNode->child[c-'a'];
if(pNode==NULL) return false;
}
return pNode->isword;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
if(prefix.length()<=0) return true;
TrieNode *pNode = root;
for(int i=0; i<prefix.length(); ++i)
{
char c = prefix[i];
pNode = pNode->child[c-'a'];
if(pNode==NULL) return false;
}
return true;
}
private:
TrieNode *root;
};
/**
* Your Trie object will be instantiated and called as such:
* Trie obj = new Trie();
* obj.insert(word);
* bool param_2 = obj.search(word);
* bool param_3 = obj.startsWith(prefix);
*/
参考链接: https://leetcode.com/problems/implement-trie-prefix-tree/solution/
https://blog.youkuaiyun.com/sunao2002002/article/details/46661761