如何处理 "invalid use of non-static data member" in class C++ 实现?
How to handle "invalid use of non-static data member" in class Implementation in c++?
我一直在尝试解决 LeetCode 上的单词搜索 II 问题,该问题需要使用 Trie 来帮助提高回溯调用的效率,并且基本上会使用尝试,我一直在尝试实现自己的 trie class 但我 运行 在我的 remove
函数中遇到了障碍,它需要 root 的副本,但我不确定如何给它一个。这是我遇到问题的部分:
TrieNode* crawl = root
in the function remove(string word, TrieNode* crawl = root, int depth = 0)
The error: invalid use of non-static data member 'Trie::root'
I don't know the correct way to do it.
TrieNode* remove(string word, TrieNode* crawl = root, int depth = 0) {
if(!crawl) return nullptr;
if(depth == word.size()) {
if(crawl->isLeaf) crawl->isLeaf = false;
if(isEmpty(crawl)) {
delete crawl;
crawl = nullptr;
}
return crawl;
}
int index = word[depth] - 'a';
crawl->arr[index] = remove(word, crawl->arr[index], depth + 1);
if(isEmpty(crawl) && crawl->isLeaf == false) {
delete crawl;
crawl = nullptr;
}
return crawl;
}
这是我的 Trie class 的样子:
class Trie {
private:
TrieNode* root;
public:
Trie() : root(new TrieNode()) {};
void insert(const string &word) {
auto crawl = root;
// does it's thing
}
bool search(const string &word) {
auto crawl = root;
// does it's thing
}
bool isPrefix(const string &word) {
auto crawl = root;
// does it's thing
}
bool isEmpty(TrieNode* root) {
for(int i = 0; i < 26; i++) if(root->arr[i]) return false;
return true;
}
TrieNode* remove(string word, TrieNode* crawl = root, int depth = 0) {
以此作为TrieNode:
struct TrieNode {
bool isLeaf;
vector<TrieNode*> arr;
TrieNode() : isLeaf(false), arr(26, nullptr) {};
};
编辑:特别感谢@SPD 建议改进删除功能
您不能将成员变量用作默认参数。
但是代替:
TrieNode* remove(string word, TrieNode* crawl = root, int depth = 0) {
//...
你可以做到
TrieNode* remove(string word, TrieNode* crawl = nullptr, int depth = 0) {
if (!crawl) {
crawl = root;
}
//...
@darune 的替代答案是超载:
TrieNode* remove(const string& word)
{
return remove(word, root);
}
TrieNode* remove(string word, TrieNode* crawl, int depth = 0) {
//...
几点建议:
- 你真的不需要一个 Trie class,TrieNode 就足够了。所有操作insert/remove都可以移到TrieNode,你可能会发现更多'natural'写TrieNode
的成员函数
- 如果您坚持现有设计并删除抓取本身,然后删除
crawl = nullptr
,我认为您需要通过指针引用而不是仅仅通过指针来传递抓取。
- #2 的替代方法是删除调用堆栈中的 crawl。 remove() 现在 returns 一个布尔值,指示调用者是否可以安全地删除此节点。下面的示例代码。
- 最后,请考虑使用托管指针而不是原始指针。 (这对于 leetcode 练习可能无关紧要)
bool remove(string word, TrieNode* crawl, int depth = 0) {
if(!crawl) return true;
if(depth == word.size()) {
if(crawl->isLeaf) crawl->isLeaf = false;
return isEmpty(crawl);
}
int index = word[depth] - 'a';
if (remove(word, crawl->arr[index], depth + 1)) {
// it's empty or nullptr, safe to remove
delete crawl->arr[index];
crawl->arr[index] = nullptr;
}
return !crawl->isLeaf && isEmpty(crawl);
}
我一直在尝试解决 LeetCode 上的单词搜索 II 问题,该问题需要使用 Trie 来帮助提高回溯调用的效率,并且基本上会使用尝试,我一直在尝试实现自己的 trie class 但我 运行 在我的 remove
函数中遇到了障碍,它需要 root 的副本,但我不确定如何给它一个。这是我遇到问题的部分:
TrieNode* crawl = root
in the functionremove(string word, TrieNode* crawl = root, int depth = 0)
The error: invalid use of non-static data member 'Trie::root'
I don't know the correct way to do it.
TrieNode* remove(string word, TrieNode* crawl = root, int depth = 0) {
if(!crawl) return nullptr;
if(depth == word.size()) {
if(crawl->isLeaf) crawl->isLeaf = false;
if(isEmpty(crawl)) {
delete crawl;
crawl = nullptr;
}
return crawl;
}
int index = word[depth] - 'a';
crawl->arr[index] = remove(word, crawl->arr[index], depth + 1);
if(isEmpty(crawl) && crawl->isLeaf == false) {
delete crawl;
crawl = nullptr;
}
return crawl;
}
这是我的 Trie class 的样子:
class Trie {
private:
TrieNode* root;
public:
Trie() : root(new TrieNode()) {};
void insert(const string &word) {
auto crawl = root;
// does it's thing
}
bool search(const string &word) {
auto crawl = root;
// does it's thing
}
bool isPrefix(const string &word) {
auto crawl = root;
// does it's thing
}
bool isEmpty(TrieNode* root) {
for(int i = 0; i < 26; i++) if(root->arr[i]) return false;
return true;
}
TrieNode* remove(string word, TrieNode* crawl = root, int depth = 0) {
以此作为TrieNode:
struct TrieNode {
bool isLeaf;
vector<TrieNode*> arr;
TrieNode() : isLeaf(false), arr(26, nullptr) {};
};
编辑:特别感谢@SPD 建议改进删除功能
您不能将成员变量用作默认参数。
但是代替:
TrieNode* remove(string word, TrieNode* crawl = root, int depth = 0) {
//...
你可以做到
TrieNode* remove(string word, TrieNode* crawl = nullptr, int depth = 0) {
if (!crawl) {
crawl = root;
}
//...
@darune 的替代答案是超载:
TrieNode* remove(const string& word)
{
return remove(word, root);
}
TrieNode* remove(string word, TrieNode* crawl, int depth = 0) {
//...
几点建议:
- 你真的不需要一个 Trie class,TrieNode 就足够了。所有操作insert/remove都可以移到TrieNode,你可能会发现更多'natural'写TrieNode 的成员函数
- 如果您坚持现有设计并删除抓取本身,然后删除
crawl = nullptr
,我认为您需要通过指针引用而不是仅仅通过指针来传递抓取。 - #2 的替代方法是删除调用堆栈中的 crawl。 remove() 现在 returns 一个布尔值,指示调用者是否可以安全地删除此节点。下面的示例代码。
- 最后,请考虑使用托管指针而不是原始指针。 (这对于 leetcode 练习可能无关紧要)
bool remove(string word, TrieNode* crawl, int depth = 0) {
if(!crawl) return true;
if(depth == word.size()) {
if(crawl->isLeaf) crawl->isLeaf = false;
return isEmpty(crawl);
}
int index = word[depth] - 'a';
if (remove(word, crawl->arr[index], depth + 1)) {
// it's empty or nullptr, safe to remove
delete crawl->arr[index];
crawl->arr[index] = nullptr;
}
return !crawl->isLeaf && isEmpty(crawl);
}