C++ 删除带有堆栈的二叉树

C++ 删除带有堆栈的二叉树,c++,stl,stack,binary-tree,C++,Stl,Stack,Binary Tree,我仍在研究我的二叉树,插入、查找、最大值和最小值函数到目前为止都工作得很好。接下来我想做一个删除函数。我包括了一个可以保存的堆栈-啊,见鬼,我只展示代码: class Tree { private: int value_; Tree *root_; Tree *left_; Tree *right_; std::stack<Tree*> treeStack; 我现在有错误了。这不是什么大问题-我尝试调试自己的代码-但这次它告诉我库文件中有一

我仍在研究我的二叉树,插入、查找、最大值和最小值函数到目前为止都工作得很好。接下来我想做一个删除函数。我包括了一个可以保存的堆栈-啊,见鬼,我只展示代码:

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

    std::stack<Tree*> treeStack;
我现在有错误了。这不是什么大问题-我尝试调试自己的代码-但这次它告诉我
库文件中有一个错误,我甚至没有使用它

在程序关闭之前,我得到
System.AccessViolationException
,错误代码指向
deque
文件。当然它不可能在那里,它必须是我代码中的某个指针。这让我相信我没有正确地操作堆栈,或者没有正确地推动堆栈

我做错了什么?当我调用堆栈上的.pop时,是否确实删除了节点

编辑:

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

Tree*parent=findInsertionPoint(val,root);
如果(valvalue)
父->左=新树(val,0,0);
其他的
父->右=新树(val,0,0);
treeStack.push(父级);
返回val;
就是我将元素推到堆栈上的位置


附加问题:是否必须在ctor中构建std::堆栈

听起来您可能要删除某个内容两次


确保您要删除的内容没有在其他任何地方使用或删除,特别是在调用橡皮擦树()方法之后。

根*
左*
右*
更改为自动PTR,以确保它们被销毁。然后,当您要删除一个节点时,您只需删除根节点即可;一切都很好。必须询问您为什么要使用堆栈。

您在
deque中崩溃,因为堆栈包含其中一个堆栈。如果您在崩溃后查看堆栈跟踪,那么您可以发现代码发生时正在执行的操作

看起来最后一段代码将错误的节点放在堆栈上;当然应该是新创建的节点,而不是插入点?如果向父节点添加两个节点,则父节点将在堆栈中结束两次,并将被删除两次

它应该更像

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;
Tree*parent=findInsertionPoint(val,root);
Tree*child=新树(val,0,0);
如果(valvalue)
父->左=子;
其他的
父项->右项=子项;
推(儿童);
返回val;
但我赞成DeadMGs的建议,即对
使用智能指针(但不要将
设置为
自动ptr
,如果所有节点都共享),并让它们为您清理。我不确定我是否看到了堆栈的意义;如果是为了加速树的破坏,那么在添加复杂且容易出错的优化之前,先问问自己两个问题:

  • 它是否足够慢,值得优化的开发/调试成本
  • 在树旁边构建和维护堆栈的额外运行时和内存成本值得吗
还有你的另一个问题:
堆栈将在构造函数中构建,但你不必编写任何代码来实现它。它的默认构造函数将被自动调用,这将为您提供一个可用的空堆栈


另外,除非这是一个学习练习,否则您应该使用
std::multiset
,而不是重新创建它。

您在deque中遇到一个错误,因为默认情况下std::stack将此类用作内部容器。查看堆栈定义:

template<class _Ty, class _Container = deque<_Ty> > class stack;
模板类栈;

我看到
橡皮擦树
类的一部分,也许您的
树堆栈中有
这个
,所以您正在做
删除这个
我对这个指针或它的实际内容从来都不太熟悉。我该怎么做才能确保这个指针不再抱怨了?第一眼我就看不到任何失败。这可能是我不习惯std::stack的原因,但如果错误不在发布的代码中,可能您应该包含构建堆栈的代码@克里斯蒂斯:检查一下(温度!=这个)是否有效就足够了吗?@InsertNickHere:我试过了<代码>温度!=这是真的
Temp
不是
this
。指针的一个小问题是:你应该用!=null,例如if(parent!=null){…},if(temp!=null),这使得避免/查找失败变得更容易。我已经包括了元素的插入,不,这是我的第一个delete函数。擦除功能是我的程序到目前为止调用的最后一个功能。你试过不使用删除功能吗?我已经很恼火地发现,很多时候C++会自动删除我分配的所有东西,如果我自己删除它,我会抱怨。我不明白你的意思。如果我想删除整个树而不必在树上重复出现然后备份,我只需将所有指针存储在堆栈中。提取的第一个指针位于树的底部。然后我就删除了内容。这就是为什么我想要一堆。“auto_ptrs会如何帮助我做到这一点?”SoulBeaver:如果你使用auto_ptrs,你不必在树上反复出现。您只需删除根节点,整个树就会倒下。使用auto_ptr,销毁是自动化的,而且有保障。你不必为那些堆废话操心。我不认为auto_ptr是个好选择。。。我建议改用shared_ptr。@EmbeddedProg:为什么?只有树节点有权删除其子节点,其他节点无权删除。虽然我刚刚意识到root_uu不应该是一个auto_ptr,但我没有意识到它指向了第一个节点。+1指出std::stack是一个默认使用std::deque的适配器。不过我不认为这是一个无用的练习。实现一棵树是很好的学术实践!也许有一天他会想要实现kd树、trie或其他树结构
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;
template<class _Ty, class _Container = deque<_Ty> > class stack;