如何为 Trie 树编写析构函数



我一直在做一个作业,让我们使用trie树将字典中的单词添加到树中,然后搜索它。我卡在上面的部分是类析构函数。这是我第一次不得不处理析构函数/内存管理,以下是我在搜索当前资源后的最佳猜测。

我走在正确的轨道上吗?每个节点有 27 个子节点(字母表和一个分隔符(,所以我希望它能将它们从叶子到根部全部删除。

class Trie
{
private:
    TrieNode *_root = nullptr;
    TrieNode *_current = nullptr;
    TrieNode *_child = nullptr;
    string current_word;
    bool setRoot = false;
protected:
public:
    Trie()
    {
        _root = new TrieNode{};
    }
    virtual ~Trie()
    {
        //TODO: clean up memory
        DestroyRecursive(_root);
    }
    void Trie::DestroyRecursive(TrieNode* node)
    {
        if (node != nullptr)
        {
            for (TrieNode* child : node->getChildren())
            {
                delete(child);
            }
        }
    }

如何检查析构函数是否正常工作?我正在使用Visual Studio。

你的DestroyRecursive实际上不是递归的

您需要在叶节点上调用delete,并在具有子节点的节点上递归。

void Trie::DestroyRecursive(TrieNode* node)
{
    if (node != nullptr)
    {
        if (node->getChildren().size() == 0)
        {
            // delete the leaf node
            delete(node);
            return;
        }
        for (TrieNode* child : node->getChildren())
        {
            DestroyRecursive(child);
        }
    }
}

这可能会出错,具体取决于对TrieNode结构的依赖性。例如,它是否有一个非平凡的析构函数?

通过替换指向 std::的原始指针可以避免很多这种情况shared_ptr

std::shared_ptr<TrieNode> _root = nullptr;
vector<shared_ptr<TrieNode>> _child = nullptr;
Trie()
{
    _root = std::make_shared<TrieNode>();
}

然后在大多数情况下,您不需要析构函数。 std::vectorshared_ptr 将负责在超出范围时调用相应内存上的delete。请注意,所有权中没有循环依赖。如果将来添加父指针,它必须是原始指针或 std::weak_ptr

如何检查析构函数是否正常工作?我正在使用视觉对象 演播室。

您可以放置一个断点来检查代码是否被命中。

最新更新