力扣-208-实现Tire
和LRU一样是实现数据结构的题目
首先,对于树结构,我们要定义树节点:
- 前缀树是多叉树结构,所以子节点数不固定,这里用一个指向子节点的指针数组来保存子节点
为什么是长度伪26代表26个字母的定长数组?
- bool值,标记当前节点是否是结束位置,即:根节点到当前节点的路径字符串存在
vector<Trie*> children;
bool isEnd;
因为封装了操作,所以才用类,而不是结构体吗?
来想一想为什么它这里用的是一个26长度的数组
因为这里的字符组成是固定的,这样做能最大优化空间占用,用数组下标(char当int操作ACSII码)确定字母
不然就要向那边一样,用map
插入
将一个字符串插入到前缀树中,即从头开始遍历字符串的每一个字符,从根节点的子节点开始比对,如果没有,就新加入一个,将指针更新为子节点,循环这一过程,并在结束后将最后一个节点的bool值置true
void insert(string word) {
Trie* node = this;
for (char ch: word) {
ch -= 'a';
if (node->children[ch] == nullptr)
node->children[ch] = new Trie();
node = node->children[ch];
}
node->isEnd = true;
}
完整代码
class Trie {
private:
vector<Trie*> children;
bool isEnd;
Trie* searchPrefix(string prefix) {
Trie* node = this;
for (char ch : prefix) {
ch -= 'a';
if (node->children[ch] == nullptr)
return nullptr;
node = node->children[ch];
}
return node;
}
public:
Trie():children(26),isEnd(false){}
void insert(string word) {
Trie* node = this;
for (char ch: word) {
ch -= 'a';
if (node->children[ch] == nullptr)
node->children[ch] = new Trie();
node = node->children[ch];
}
node->isEnd = true;
}
bool search(string word) {
Trie* node = this->searchPrefix(word);
return node != nullptr && node->isEnd;
}
bool startsWith(string prefix) {
return this->searchPrefix(prefix) != nullptr;
}
};
测试代码
int main() {
Trie trie;
trie.insert("string");
trie.insert("stdmain");
cout << trie.search("unfea") <<endl;
cout << trie.search("stdmain") << endl;
cout << trie.startsWith("tf") << endl;
cout << trie.startsWith("st");
return 0;
}