c++中如何处理类Implementation中的 "无效使用非静态数据成员"?

问题描述 投票:0回答:3

我一直想解决LeetCode上的一个问题Word Search II,需要使用Trie来帮助提高回溯调用的效率,基本上要使用tries,我一直想实现自己的Trie类,但是在我的 remove 函数,它需要一个root的副本,但我不知道如何给它一个。以下是我遇到问题的部分。

TrieNode* crawl = root 在函数中 remove(string word, TrieNode* crawl = root, int depth = 0)

错误:无效使用非静态数据成员'Trie::root'。

我不知道正确的方法是什么。

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 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提出的关于移除功能的改进建议。

c++ class oop pointers trie
3个回答
2
投票

@darune的答案的另一个选择是有一个重载。

TrieNode* remove(const string& word)
{
    return remove(word, root);
}
TrieNode* remove(string word, TrieNode* crawl, int depth = 0) { 
//...

1
投票

你不能使用成员变量作为默认参数。

然而,我们可以用以下方法来代替。

TrieNode* remove(string word, TrieNode* crawl = root, int depth = 0) { 
//...

你可以这样做

TrieNode* remove(string word, TrieNode* crawl = nullptr, int depth = 0) { 
  if (!crawl) {
    crawl = root;
  }
  //...

1
投票

一些建议。

  1. 你并不需要一个Trie类,TrieNode就足够了。所有操作insertremove都可以移到TrieNode中,你可能会发现写TrieNode的成员函数更 "自然"。
  2. 如果你坚持你现有的设计,并删除爬行本身,然后是 crawl = nullptr我认为你需要通过指针引用来传递crawl,而不仅仅是指针。
  3. remove()现在返回一个布尔值,表示调用者是否可以安全地删除这个节点。示例代码如下。
  4. 最后,请考虑使用managed ptrs而不是raw ptrs。(对于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);
} 
© www.soinside.com 2019 - 2024. All rights reserved.