头指针不包含二叉树中的子节点
Posted
技术标签:
【中文标题】头指针不包含二叉树中的子节点【英文标题】:Head pointer doesn't contain child nodes in Binary Tree 【发布时间】:2020-10-30 01:08:41 【问题描述】:我正在复制一棵二叉树,但我遇到了一个问题,即我的新树的根指针最终只包含要复制的第一个节点,而没有其他节点。我认为这个问题与这样一个事实有关,即当我在辅助函数的递归中传递指针时,由于某种原因,它们没有被重新分配给新的节点内存地址。就像在helper(t1->left, t2->left)
t2->left 实际上永远不会成为我想要它拥有的值,它保持为空。
bool first_time = true;
TreeNode* ref = NULL;
void helper(TreeNode* t1, TreeNode* t2)
if(t1)
t2 = new TreeNode(t1->val);
if(first_time)
ref = t2;
first_time = false;
helper(t1->left, t2->left);
helper(t1->right, t2->right);
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2)
TreeNode* tree1 = new TreeNode(1);
tree1->left = new TreeNode(2);
tree1->right = new TreeNode(3);
helper(tree1, NULL);
return ref;
【问题讨论】:
【参考方案1】:这里有几个问题。
首先,ref
和first_time
是严重的缺陷,您应该避免编写具有这种全局状态的代码。它不是可重入的,也不是线程安全的。
其次,您尝试写入 t2 指针并将调用者的指针更改为该值。但是,您传递的是 t2 的副本,因此对其的写入将会丢失。
清理它并不需要太多,只需更改您的函数以获取 对指针的引用,然后写入 t2 将持续返回给调用者。注意,t2 是一个“out”参数,所以初始调用者会得到通过这个指针返回的树副本。
这是一个固定版本:
void helper(TreeNode* t1, TreeNode*& t2)
if(t1)
t2 = new TreeNode(t1->val);
helper(t1->left, t2->left);
helper(t1->right, t2->right);
这是您的测试函数的样子:
TreeNode* copyTest()
TreeNode* tree1 = new TreeNode(1);
tree1->left = new TreeNode(2);
tree1->right = new TreeNode(3);
TreeNode* tree2 = nullptr;
helper(tree1, tree2); // tree2 is written to as new root.
return tree2;
但如果不需要 out 参数,一般不建议使用。
为什么不编写你的 copyTree 函数来返回一个指向复制树的指针? 基本上去掉in中的第二个参数,分配当前树的一个副本,向下递归,将每个子副本附加到当前节点的父副本,并返回父节点:
TreeNode* copyTree(TreeNode* tree)
TreeNode* ret = nullptr;
if (tree)
ret = new TreeNode(tree->val);
ret->left = copyTree(tree->left);
ret->right = copyTree(tree->right);
return ret;
除非您非常小心,否则这不是防止泄漏的好方法,但它有助于理解递归和树结构。
【讨论】:
这条评论给了我很大的帮助,我非常感谢你提到的所有额外建议,让我成为更好的程序员。【参考方案2】:检查您的全局变量 first_time
和 ref
。
if (first_time)
ref = t2; // global
first_time = false; // global set to never go here again
这实际上是您的问题的根源 - 一旦您将第一个节点传递给您的函数,您就更改了其他全局变量 ref
,之后再也不会在任何地方更改它。因此,基本上,在每个递归调用中,您都会使用悬空指针泄漏内存。
可能,您应该将参数 first_time
传递给您的函数,并可能将 ref
作为可分配参数传递
【讨论】:
以上是关于头指针不包含二叉树中的子节点的主要内容,如果未能解决你的问题,请参考以下文章