C++ 此添加节点功能是否会导致内存问题?
我编写了一个递归函数,在二叉搜索树中插入一个新节点。函数如下所示C++ 此添加节点功能是否会导致内存问题?,c++,binary-search-tree,C++,Binary Search Tree,我编写了一个递归函数,在二叉搜索树中插入一个新节点。函数如下所示 void add_node(node *it, int val) { node * temp = new node; temp->data=val; temp->left=NULL; temp->right=NULL; if(root==NULL) { root=temp; } else if(it->data > va
void add_node(node *it, int val)
{
node * temp = new node;
temp->data=val;
temp->left=NULL;
temp->right=NULL;
if(root==NULL)
{
root=temp;
}
else if(it->data > val)
{
if(it->left==NULL)
{
it->left=temp;
return;
}
else
add_node(it->left, val);
}
else
{
if(it->right==NULL)
{
it->right=temp;
return;
}
else
add_node(it->right, val);
}
}
此函数在每次递归调用临时节点时创建临时节点。若BST的高度很大,这会导致一些问题(和内存相关)吗
此函数在每次递归调用临时节点时创建临时节点
节点分配不是临时的;它完全泄露了。唯一保留的是最后一个。事实上,任何需要一个以上跃点的遍历都会在激活堆栈中的任何先前递归调用中泄漏节点分配
有两件事可以解决这个问题
root
。使用对指针的引用作为输入参数类型,允许您直接引用树中的实际指针(而不仅仅是指针所持有的地址)。这包括根
指针节点
结构看起来像这样(偏执于删除复制和分配):
输出{显然不同)
此函数在每次递归调用临时节点时创建临时节点
该节点分配不是临时的;它是完全泄漏的。唯一保留的是最后一个。事实上,任何需要一个以上跃点的遍历都会在激活堆栈中的任何先前递归调用中泄漏节点分配
有两件事可以解决这个问题
根
进行编码。使用指针引用作为输入参数类型,允许您直接引用树中的实际指针(而不仅仅是它们所持有的地址)。这包括根
指针节点
结构看起来像这样(偏执于删除复制和分配):
输出{显然不同)
你必须对特定的区域进行配置/测试。当当前节点和它的子节点都不是叶子时,会发生什么样的临时变量?你可能想考虑一下STD::UnQuyjpTR以使内存管理更容易。这是非常复杂的。如果你想添加一个新的节点,你只需要一次一次地创建新的节点。在树中创建新节点。是的,它会泄漏;树中的每个跃点(最后一个除外)都有一个节点。在最终发现它将挂起的位置之前,不要创建新节点。不相关的,将指针引用作为第一个参数类型更容易。这使用尾部递归,所有尾部递归都可以重写为循环。这将也就是说,您不必删除未使用节点的泄漏,因为每个调用都将使用创建的节点(在循环找到放置节点的位置后)你必须对特定的区域进行配置/测试。当当前节点和它的子节点都不是叶子时,会发生什么样的临时变量?你可能想考虑一下STD::UnQuyjpTR以使内存管理更容易。这是非常复杂的。如果你想添加一个新的节点,你只需要一次一次地创建新的节点。在树中创建新节点。是的,它会泄漏;树中的每个跃点(最后一个除外)都有一个节点。在最终发现它将挂起的位置之前,不要创建新节点。不相关的,将指针引用作为第一个参数类型更容易。这使用尾部递归,所有尾部递归都可以重写为循环。这将也就是说,您不必删除未使用节点的泄漏,因为每个调用都将使用创建的节点(在循环找到放置节点的位置后)
struct node
{
node(int val)
: value(val)
, left(nullptr)
, right(nullptr)
{
std::cout << "node::node(" << value << ")\n";
}
node(const node&) = delete;
node& operator=(const node&) = delete;
int value;
node *left;
node *right;
};
// note reference-to-pointer as first arg type
void add_node(node *& refp, int value)
{
if (refp == nullptr)
{
refp = new node(value);
}
else if (value < refp->value)
{
add_node(refp->left, value);
}
else
{
add_node(refp->right, value);
}
}
#include <iostream>
#include <random>
struct node
{
node(int val)
: value(val)
, left(nullptr)
, right(nullptr)
{
std::cout << "node::node(" << value << ")\n";
}
node(const node&) = delete;
node& operator=(const node&) = delete;
int value;
node *left;
node *right;
};
void add_node(node *& refp, int value)
{
if (refp == nullptr)
{
refp = new node(value);
}
else if (value < refp->value)
{
add_node(refp->left, value);
}
else
{
add_node(refp->right, value);
}
}
void inorder(const node* root)
{
if (root)
{
inorder(root->left);
std::cout << root->value << ' ';
inorder(root->right);
}
}
void free_tree(node *& root)
{
if (root)
{
free_tree(root->left);
free_tree(root->right);
delete root;
root = nullptr;
}
}
int main()
{
node *root = nullptr;
std::mt19937 rng{ std::random_device{}() };
std::uniform_int_distribution<> dist(1, 99);
for (int i = 0; i < 20; ++i)
add_node(root, dist(rng));
inorder(root);
std::cout.put('\n');
free_tree(root);
}
node::node(79)
node::node(28)
node::node(39)
node::node(82)
node::node(10)
node::node(11)
node::node(22)
node::node(4)
node::node(19)
node::node(85)
node::node(38)
node::node(66)
node::node(45)
node::node(15)
node::node(23)
node::node(73)
node::node(52)
node::node(45)
node::node(73)
node::node(84)
4 10 11 15 19 22 23 28 38 39 45 45 52 66 73 73 79 82 84 85