简体   繁体   English

二叉搜索树析构函数

[英]Binary Search Tree Destructor

Working on implementing my own BST in C++ for the experience of dealing with such structures.致力于在 C++ 中实现我自己的 BST,以获得处理此类结构的经验。

I've had trouble implementing a destructor.我在实现析构函数时遇到了麻烦。 I found in my studies, that one can't really have a recursive destructor (due to a flag that doesn't allow the destructor to be called on the same object after having been called), but I'm not really sure of any other way to successfully clean up all the nodes in the tree.我在我的研究中发现,一个人不能真正有递归析构函数(由于一个标志不允许在调用后在同一个对象上调用析构函数),但我不确定任何成功清理树中所有节点的另一种方法。

To compensate, I've created a helper function - however this throws an unresolved external error on the 'delete n' line.作为补偿,我创建了一个辅助函数 - 但是这会在“删除 n”行上引发未解决的外部错误。 Any tips?有小费吗?

Code:代码:

void BinSearchTree::Clear(tNode* n)
{
    if (n->left != NULL)
        Clear(n->left);
    if (n->right != NULL)
        Clear(n->right);
    delete n;
    n = NULL;
    size--;
}

You can have a recursive destructor;你可以有一个递归析构函数; what you can't do is delete the same object twice.你不能做的是删除同一个对象两次。

A typical way to delete a tree in C++ might be something like this:在 C++ 中删除树的典型方法可能是这样的:

BinSearchTree::~BinSearchTree()
{
   delete _rootNode;  // will recursively delete all nodes below it as well
}

tNode::~tNode()
{
   delete left;
   delete right;
}

Regarding the unresolved external error -- is that error thrown when you try to compile/link the program?关于未解决的外部错误——当您尝试编译/链接程序时是否抛出该错误? If so, it's probably because the code for the tNode class (and in particular the tNode destructor, if you declared one) doesn't exist or isn't getting compiled into your project.如果是这样,那可能是因为 tNode 类的代码(特别是 tNode 析构函数,如果您声明了一个)不存在或没有被编译到您的项目中。

Previous answers have pointed out that the unresolved external error is likely caused by a tNode destructor that is declared but not defined in a translation unit that the linker can see.以前的答案指出,未解决的外部错误可能是由 tNode 析构函数引起的,该析构函数在链接器可以看到的翻译单元中声明但未定义。

However, you have a second error: You appear to believe that setting n to null does something it doesn't do.但是,您还有第二个错误:您似乎相信将 n 设置为 null 会做一些它没有做的事情。 The pointer value n is passed by value, not by reference, such that changing its value (eg by assigning NULL) has no effect after the function returns.指针值 n 是按值传递的,而不是按引用传递的,因此在函数返回后更改其值(例如,通过分配 NULL)不会产生任何影响。

This will probably give you errors when you clear the tree and expect the root node pointer to have been set to NULL, when it remains a dangling pointer to freed memory.当您清除树并期望根节点指针已设置为 NULL 时,这可能会给您带来错误,而它仍然是指向已释放内存的悬空指针。 The result will be runtime error, not your linker error.结果将是运行时错误,而不是您的链接器错误。

void BinSearchTree::Clear(tNode **N)
{
    tNode * n = *N;
    if (n->left != NULL)
        Clear(n->left);
    if (n->right != NULL)
        Clear(n->right);
    delete n;
    *N = NULL;
    size--;
}

Will do what you expect.会做你所期望的。

The problem is that in you class you probably declared that the node structure has a custom destructor, but you don't provide it so at link time the compiler is complaining a piece is missing.问题是,在您的类中,您可能声明节点结构具有自定义析构函数,但是您没有提供它,因此在链接时编译器抱怨缺少一个片段。

If you don't need any more custom code in the destructor then you can just remove the destructor from the struct declaration and your program will compile fine.如果您在析构函数中不需要更多自定义代码,那么您只需从结构声明中删除析构函数,您的程序就可以正常编译。

Note however that there is no problem at all to have a destructor of to destory children nodes (see Brendan Long answer).但是请注意,使用 destory 子节点的析构函数完全没有问题(请参阅 Brendan Long 的回答)。 If you ran into problems while attempting that the issue you faced must me something else.如果您在尝试遇到问题时遇到问题,那么您遇到的问题一定是我的其他问题。

Just use a destructors.只需使用析构函数。 It sounds like your problem is that you were trying to call the destructors directly, but the language handles this for you.听起来您的问题是您试图直接调用析构函数,但是语言会为您处理这个问题。 They're called either when you leave a stack allocated object's scope, or when you delete an object.当您离开堆栈分配对象的范围或删除对象时,它们会被调用。

All you should need is this:你只需要这样:

~BinSearchTree() {
    delete left;
    delete right;
}

delete will call their destructors. delete将调用它们的析构函数。

Note: It's perfectly safe to delete NULL , it has no effect .注意: delete NULL是完全安全的,它没有任何效果

How about automating it:如何自动化它:

class BinSearchTree
{
    std::auto_ptr<tNode>   left;
    std::auto_ptr<tNode>   right;

    BinSearchTree(BinSearchTree const&);
    BinSearchTree& operator=(BinSearchTree const&); // private
};

Now destruction is automatic.现在销毁是自动的。 :-) :-)

You can also use recursion, you just need to change the function header to:您也可以使用递归,您只需要将函数头更改为:

void remove(node*& root) 

and it will work.它会起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM