我一直在为一个更大的项目开发一个简单的二叉搜索树。我理解二叉搜索树的概念,并且只是在C ++中实现语法的麻烦。我故意不使用boost的树容器。我的树代码如下。
struct Tree{
int nodeValue;
Tree *nodeChild1;
Tree *nodeChild2;
Tree(int userProvidedValue){
nodeValue = userProvidedValue;
nodeChild1 = NULL;
nodeChild2 = NULL;
}
static void placeValue(Tree &parent, int value);
static Tree findValue(Tree parent, int value);
static void crawl(Tree parent);
~Tree(){
delete nodeChild1;
delete nodeChild2;
}
};
void Tree::placeValue(Tree &parent, int value){
Tree node = Tree(value);
cout<<"made node"<<endl;
if(value>parent.nodeValue){
cout<<"eval node child 2"<<endl;
if(parent.nodeChild2 ==NULL){
cout<<"reaching this";
parent.nodeChild2 = &node;
}
else{
placeValue(*parent.nodeChild2, value);
}
}
if(value<=parent.nodeValue){
cout<<"eval node child 1"<<endl;
if(!parent.nodeChild1){
cout<<"assigning"<<endl;
parent.nodeChild1 = &node;
}
else{
placeValue(*parent.nodeChild1, value);
}
}
}
但是每当我用Tree parent = Tree(5)
构造一个树然后用Tree::placeValue(parent, 4)
添加另一个节点时,它编译得很好但会弹出一条消息告诉我exe已经崩溃了。
任何人都可以帮助我了解这次崩溃的来源吗?提前谢谢。
爬网树的代码如下所示:
void Tree::crawl(Tree parent){
cout<<parent.nodeValue<<endl;
if(NULL!=parent.nodeChild1){
crawl(*parent.nodeChild1);
}
if(NULL!=parent.nodeChild2){
crawl(*parent.nodeChild2);
}
}
奖金问题:当Tree :: crawl采用Tree&amp; parent的参数而不是Tree parent时,它运行正常。但没有&amp;但它失败了。任何人都可以解释为什么会这样吗?
答案 0 :(得分:3)
您在堆栈中分配包含新值的Tree()
实例,即Tree node = Tree(value);
。当函数调用返回时,该实例被销毁,因此当您稍后尝试访问它时,程序崩溃。
此外,您的析构函数会对其子项调用delete
,因此您可能应该在堆上分配Tree
实例来解决您的问题:Tree* node = new Tree(value);
答案 1 :(得分:3)
您必须在堆上分配树。
Tree node = Tree(value);
在这里,您将在堆栈上分配一个树。该变量的地址将在超出范围后处理。要在堆上分配它,只需使用new运算符:
Tree *node = new Tree(value);
然后将其指定为父级的子级:
parent.nodeChild2 = node;
关于Tree :: crawl错误,它基于相同的错误。你继续在堆栈上分配树,因此一旦它超出范围,它的析构函数被调用,删除(ing)nodeChild1和nodeChild2。您应该通过使用指针或始终使用引用来管理这些类型的结构,这样当函数结束时,不会调用Tree的析构函数。因此:
void Tree::crawl(const Tree &parent){
cout<<parent.nodeValue<<endl;
if(NULL!=parent.nodeChild1){
crawl(*parent.nodeChild1);
}
if(NULL!=parent.nodeChild2){
crawl(*parent.nodeChild2);
}
}
这应该这样做。记得在Tree :: findValue上做同样的事情,你应该为这个函数使用这个签名:
static Tree findValue(const Tree &parent, int value);
答案 2 :(得分:0)
Tree node = Tree(value);
node
具有声明它的程序块的范围。退出Tree::placeValue
后将自动删除它。当你获得指针(parent.nodeChild2 = &node;
)时,它将在退出后指向任何内容并尝试取消引用它将导致未定义的行为。像这样动态创建它:
Tree * node = new Tree(value);