Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。
请你实现 Trie 类:
Trie()
初始化前缀树对象。void insert(String word)
向前缀树中插入字符串word
。boolean search(String word)
如果字符串word
在前缀树中,返回true
(即,在检索之前已经插入);否则,返回false
。boolean startsWith(String prefix)
如果之前已经插入的字符串word
的前缀之一为prefix
,返回true
;否则,返回false
。
示例:
输入 ["Trie", "insert", "search", "search", "startsWith", "insert", "search"] [[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]] 输出 [null, null, true, false, true, null, true] 解释 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
提示:
1 <= word.length, prefix.length <= 2000
word
和prefix
仅由小写英文字母组成insert
、search
和startsWith
调用次数 总计 不超过3 * 10^4
次
难点:
1.不理解创建的对象,函数之间的调用关系
本体的结构与java中的类很像
Trie()是在编译程序时自动调用的方法,常用于初始化成员变量,创建对象时仅运行一次
其他方法都是对象的方法,在代码创建obj对象后可以直接通过对象obj访问
2.树的结构
代码:
class Trie {
private:
// 定义Trie树的结构
bool isEnd; //用于标记当前节点是否是某个单词的结尾。如果 isEnd 为 true,则表示从根节点到这个节点的路径构成了一个完整的单词
//注意这里定义的是一个大小为 26 的指针数组,其中每个元素都是指向 Trie 类的指针。
Trie* next[26];//字母表的映射表 *为链表指针,相当于当前节点有26个指针,并没有显性地说明每个指针对应的值,但是通过指针下标+‘a'可以判断出来
public:
Trie() {//对节点进行初始化,本题的结构跟Java的类很像,Trie()就是构造器,当创建一个Trie类时,系统会自动运行构造器,所以一般可以在构造器中进行初始化
isEnd=false;
memset(next,0,sizeof(next)); //
}
void insert(string word) {
Trie* node =this; //this是一个特殊指针,指向当前对象的实例,实现从根节点开始遍历 Trie。
char val;
for(int i=0;i<word.size();i++){
val=word[i];
if(node->next[val-'a']==NULL){//因为有头节点,所以判断的是下一个节点是否存在
//检查val对应的子节点是否存在,不存在就创建一个
node->next[val-'a']=new Trie(); //下标中char会自动转换为int类型?
}
node=node->next[val-'a'];
}
node->isEnd=true;//word的最后一个单词所在的节点
}
bool search(string word) {
Trie* node=this;//this指向的是当前对象的地址,也就是根节点
char val;
// for(int i=0;i<word.size();i++){
// val=word[i];
// //指针指向当前节点
// node=node->next[val-'a'];
// if(node==NULL) return false;
// }
// return node->isEnd;
for(int i=0;i<word.size();i++){
val=word[i];
if(node->next[val-'a']!=NULL){
node=node->next[val-'a'];
}
else{
return false;
}
if(i==word.size()-1){
if(node->isEnd==true)
return true;
else{
return false;
}
}
}
return node->isEnd;
}
//判断 Trie 中是或有以 prefix 为前缀的单词.与search类似
bool startsWith(string prefix) {
Trie* node=this;
char val;
for(int i=0;i<prefix.size();i++){
val=prefix[i];
node=node->next[val-'a'];
if(node==NULL) return false;
}
return true;
}
};
/**
* 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);
*/