如何处理 "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) { 
//...

几点建议:

  1. 你真的不需要一个 Trie class,TrieNode 就足够了。所有操作insert/remove都可以移到TrieNode,你可能会发现更多'natural'写TrieNode
  2. 的成员函数
  3. 如果您坚持现有设计并删除抓取本身,然后删除 crawl = nullptr,我认为您需要通过指针引用而不是仅仅通过指针来传递抓取。
  4. #2 的替代方法是删除调用堆栈中的 crawl。 remove() 现在 returns 一个布尔值,指示调用者是否可以安全地删除此节点。下面的示例代码。
  5. 最后,请考虑使用托管指针而不是原始指针。 (这对于 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);
}