问题描述
所以我有一个简单的 C++ 代码片段,它应该将一个节点插入到二叉搜索树中。如果值插入成功,则返回 true,如果值已经在树中,则返回 false。
struct Node {
int data;
Node* parent = nullptr;
Node* left = nullptr;
Node* right = nullptr;
};
bool insert(Node& root,int data) {
if (data > (root.data)) {
if ((root.right) == nullptr) {
Node newNode = {data,&root};
root.right = &newNode;
return true;
} else {
return insert(*root.right,data);
}
}
else if (data < (root.data)) {
if ((root.left) == nullptr) {
Node newNode = {data,&root};
root.left = &newNode;
return true;
} else {
return insert(*root.left,data);
}
}
else {
return false; // if both values are equal
}
}
在测试我的功能时,我发现了一些奇怪的东西。当我不打印函数的返回值时,它给出了正确答案(20):
Node root = {50};
insert(root,20);
cout << (root.left->data) << endl;
但是,当我do打印返回值时,它给出了错误的结果 (0):
Node root = {50};
cout << insert(root,20) << endl;
cout << (root.left->data) << endl;
我无法理解为什么会发生这种情况,但我最好的选择是因为一些奇怪的内存问题,也许没有为结构分配新的内存?我来自 Python,其中内存管理是自动处理的,所以我仍然习惯这样的情况。
解决方法
你在那里调用未定义的行为:
Node newNode = {data,&root};
root.right = &newNode;
这将在您的树中存储堆栈变量的地址。一旦函数返回,取消引用此 Node
的子代就不再合法了。从那里开始,任何事情都可能发生。
你可能想要这样的东西:
Node* newNode = new Node;
newNode.data = data;
newNode.root = root;
...
root.right = newNode;
编辑:请记住,每当您在代码中放入 new
时,您都需要一个匹配的 delete
。为了避免这种麻烦,现代方法是使用 unique_ptr
。你应该调查一下。在您的情况下,由于您保留指向根的指针,因此您需要 shared_ptr
和/或 weak_ptr
。