/**
* Initialize your data structure here.
*/
var Trie = function () {
// 根节点使用一个空对象,单词的每个字母作为对象的一个key
this.root = {};
// 使用一个固定的标记,标记一个节点为前缀树的根节点
// 此处使用Symbol标记,避免重复
this.endOfWord = Symbol('EOF');
};
/**
* Inserts a word into the trie.
* @param {string} word
* @return {void}
*/
Trie.prototype.insert = function (word) {
// 当一个单词插入前缀树时,都从根节点开始插入
let node = this.root;
// 逐个字母遍历单词
for (const char of word) {
// 如果字母未在前缀树中川建国节点,则创建一个新节点
node[char] = node[char] || {};
// 移动节点,向下遍历
node = node[char];
}
// 标记当前节点是一个单词的结束位置
node[this.endOfWord] = this.endOfWord;
};
/**
* Returns if the word is in the trie.
* @param {string} word
* @return {boolean}
*/
Trie.prototype.search = function (word) {
// 单词的搜索从根节点开始
let node = this.root;
// 在前缀树中查找单词的每个字母
for (const char of word) {
// 如果当前字母不存在于前缀树,该单词也一定不存在
if (!node[char]) {
return false;
}
// 移动节点,向下查找
node = node[char];
}
// 如果该单词的最后一个字母对应的节点,在前缀树中被标记为单词结尾,才表示这个单词在前缀树中存在
return node[this.endOfWord] === this.endOfWord;
};
/**
* Returns if there is any word in the trie that starts with the given prefix.
* @param {string} prefix
* @return {boolean}
*/
Trie.prototype.startsWith = function (prefix) {
// 从根节点开始判断单词是否存在
let node = this.root;
// 在前缀树中查找单词的每个字母
for (const char of prefix) {
// 如果当前字母不存在于前缀树,该单词也一定不存在
if (!node[char]) {
return false;
}
// 移动节点,向下查找
node = node[char];
}
// 此处无需判断单词是否完整的在前缀树中存在,只要前缀树中存在单词所有字母即可
return true;
};
评论