简体   繁体   English

删除具有堆栈的二叉树

[英]Delete a Binary Tree with a Stack

I'm still working on my binary trees, and the insertion, lookup, maximum, minimum functions are all working great so far. 我仍在工作我的二进制树,到目前为止,插入,查找,最大,最小功能都非常有效。 So I want to do a deletion function next. 因此,我接下来要执行删除功能。 I included a Stack which saves- ah hell, I'll just show the code: 我包括一个可以节省的堆栈-啊,我只显示代码:

class Tree
{
private:
    int value_;
    Tree *root_;
    Tree *left_;
    Tree *right_;

    std::stack<Tree*> treeStack;

The delete function: 删除功能:

int Tree::eraseTree()
{
    while( !treeStack.empty() )
    {
        Tree *temp = treeStack.top();
        treeStack.pop();
        delete temp;
    }
    if( treeStack.empty() )
        return 1;
    else
        return -1;
}

I'm getting errors now. 我现在遇到错误。 This wouldn't be much of a problem- I try to debug my own code- except this time it's telling me there is an error in the <deque> library file which I am not even using. 这不是什么大问题-我尝试调试我自己的代码-除非这次是告诉我<deque>库文件中有一个我什至没有使用的错误。

Before the program shuts off I get System.AccessViolationException and the faulty code points to the deque file. 在程序关闭之前,我得到了System.AccessViolationException ,错误的代码指向了deque文件。 Of course it can't be there, it has to be some pointer in my code. 当然不能存在,它必须在我的代码中有一些指针。 Which leads me to believe I am not working the stack correctly, or not pushing to the stack correctly. 这使我相信我没有正确地处理堆栈,或者没有正确地推动堆栈。

What am I doing wrong here? 我在这里做错了什么? Am I actually deleting the nodes when I call .pop on the stack? 当我在堆栈上调用.pop时,实际上是在删除节点吗?

EDIT: 编辑:

if( !root_ )
{
    root_ = new Tree(val, 0, 0);
    treeStack.push(root_);
    return val;
}

And

Tree *parent = findInsertionPoint(val, root_);
    if( val < parent->value_ )
        parent->left_  = new Tree(val, 0, 0);
    else
        parent->right_ = new Tree(val, 0,0);

    treeStack.push(parent);
    return val;

Is where I am pushing my elements on the stack. 是我将元素推入堆栈的地方。

Additional Question: Does a std::stack have to be built in the ctor? 附加问题:是否必须在ctor中构建std :: stack?

Change root_* , left_* and right_* into auto_ptrs to guarantee their destruction. root_*left_*right_*更改为auto_ptrs,以确保销毁它们。 Then when you come to delete a node, you can just delete root_.release(); 然后,当您要删除节点时,只需删除root_.release();即可。 and all is fine. 一切都很好。 Gotta ask why you're using a stack. 要问你为什么要使用堆栈。

You're crashing in deque because the stack contains one of those. 您在deque崩溃了,因为堆栈包含其中之一。 If you look at the stack trace after the crash, then you can find out what your code was doing when it happened. 如果查看崩溃后的堆栈跟踪,则可以了解代码发生时的行为。

It looks like the final snippet of code is putting the wrong node on the stack; 看起来最后的代码片段是在堆栈上放置了错误的节点。 surely it should be the newly created node, not the insertion point? 确定它应该是新创建的节点,而不是插入点吗? If you add two nodes to a parent, then the parent will end up in the stack twice, and will be deleted twice. 如果将两个节点添加到父节点,则父节点将在堆栈中结束两次,并被删除两次。

It should probably be more like 它可能应该更像

Tree *parent = findInsertionPoint(val, root_);
Tree *child = new Tree(val, 0, 0);
if( val < parent->value_ )
    parent->left_  = child;
else
    parent->right_ = child;

treeStack.push(child);
return val;

But I'd favour DeadMGs suggestion to use smart pointers for left_ and right_ (but don't make root_ an auto_ptr , if that's shared by all the nodes), and let them clean up for you. 但是我赞成DeadMG的建议,将智能指针用于left_right_ (但不要将root_ auto_ptr ,如果所有节点都共享该指针),并让它们为您清理。 I'm not sure I see the point of the stack; 我不确定我是否了解堆栈的要点; if it's to speed up the tree's destruction, then ask yourself two questions before adding a complex and error-prone optimisation: 如果要加快树的破坏速度,请在添加复杂且易于出错的优化之前先问自己两个问题:

  • is it slow enough to be worth the development/debugging cost of optimising? 它的速度是否足够值得优化的开发/调试成本?
  • is it worth the extra runtime and memory cost of building and maintaining the stack alongside the tree? 是否值得在树旁边构建和维护堆栈而需要额外的运行时和内存成本?

And your additional question: the stack will be built in the constructor, but you don't have to write any code to do it. 还有您的另一个问题: stack将在构造函数中构建,但是您不必编写任何代码即可执行此操作。 Its default constructor will be called automatically, and that will give you a usable, empty stack. 它的默认构造函数将被自动调用,这将为您提供可用的空堆栈。

Also, unless this is a learning exercise, you should use std::multiset rather than reinventing it. 另外,除非这是一项学习练习,否则应使用std::multiset而不是重新发明它。

It sounds like you might be deleting something twice. 听起来您可能要删除两次。

Make sure the stuff you're deleting isn't used or deleted anywhere else, especially after calling your eraseTree() method. 确保要删除的内容没有在其他任何地方使用或删除,尤其是在调用deleteTree()方法之后。

You got an error in deque because by default std::stack uses this class as an internal container. 由于默认情况下std :: stack将此类用作内部容器,因此deque中出现错误。 Look at the stack definition: 查看堆栈定义:

template<class _Ty, class _Container = deque<_Ty> > class stack;

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

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