简介
Trie树:又称单词查找树,字典树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
基本性质
- 根节点不包含字符,除根节点以外每个节点只包含一个字符。
- 从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。
- 每个节点的所有子节点包含的字符串不相同。
数据结构
class Trie {
private:
Trie *nxt[26]; // 26叉树
bool isEnd; //判断该字符是否为单词的末尾
};
基本函数
- void insert(string word): 将字符串word插入到 Trie 树中。其实就是将字符转化为
26
26
26(只包含大写或小写字母)个数字,然后以指针的形式进行遍历和判断,首先建立一个根节点不存储数据,然后每次遍历插入的字符串,如果该字符串中的单词在 Trie 树中,那么 root 节点就会移动到当前字符所指的 next 节点;否则就创建一个新节点来保存next节点,更新root节点,直到遍历完毕后,给这个单词进行标记,即
isEnd = true;
- bool search(string word): 判断 word字符串是否存在于 Trie 树中。遍历该字符串,如果当前字符串的next节点为空,说明该字符下面没有接任何的字符,返回 false;否则继续,直到全部遍历完毕,判断末尾字符的isEnd是否为true即可。
- bool startsWith(string prefix): 判断 prefix 是否为前缀。跟 search 操作类似,只不过不需要判断prefix 的结尾是否为单词而已。
例题 leetcode 208. 实现 Trie (前缀树)
实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。
示例:
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple"); // 返回 true
trie.search("app"); // 返回 false
trie.startsWith("app"); // 返回 true
trie.insert("app");
trie.search("app"); // 返回 true
代码实现
class Trie {
private:
Trie *nxt[26];
bool isEnd;
public:
/** Initialize your data structure here. */
Trie() {
for(int i=0; i<26; i++) nxt[i] = nullptr;
isEnd = false;
}
/** Inserts a word into the trie. */
void insert(string word) {
Trie* root = this;
for(auto ch : word) {
int id = ch - 'a';
if(root->nxt[id] == NULL) root->nxt[id] = new Trie();
root = root->nxt[id];
}
root->isEnd = true;
}
/** Returns if the word is in the trie. */
bool search(string word) {
Trie* root = this;
for(auto ch : word) {
int id = ch - 'a';
if(root->nxt[id] == NULL) return false;
root = root->nxt[id];
}
return root->isEnd;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
Trie* root = this;
for(auto ch : prefix) {
int id = ch - 'a';
if(root->nxt[id] == NULL) return false;
root = root->nxt[id];
}
return true;
}
};