【发布时间】:2020-06-08 03:55:10
【问题描述】:
我有一棵看起来像这样的二叉树
struct Node
{
int key;
double data;
Node* right;
Node* left;
};
我有这个“插入”功能用于插入新节点和构建树
void insert(Node*& p, int key, double to_be_inserted)
{
if (p == nullptr)
{
p = new Node;
p->key = key;
p->data = to_be_inserted;
p->left = nullptr;
p->right = nullptr;
}
else
{
if (p->key == key)
{
p->data = to_be_inserted;
}
else
{
Node*& newChild = (p->key > key) ? p->left : p->right;
insert(newChild, key, to_be_inserted);
}
}
}
还有一个看起来像这样的主函数
int main(int argc, char ** argv)
{
Node* root = nullptr;
insert(root, 11, 11);
insert(root, 6, 6);
insert(root, 4, 4);
insert(root, 5, 5);
insert(root, 8, 8);
insert(root, 10, 10);
insert(root, 19, 19);
insert(root, 17, 17);
insert(root, 43, 43);
insert(root, 31, 31);
insert(root, 49, 49);
printTree(root, 0);
return 0;
}
最终“打印出来”的树看起来像这样
(这个“打印输出”的意思是从左到右而不是从上到下阅读)
我不明白的是...insert 函数何时决定回溯(返回树)并构建右子树?
例如,如果我们查看main 中的insert(root, 5, 5) 和insert(root, 8, 8),为什么8 最终成为node 6 的子节点而不是node 5。根据insert 函数的逻辑,它应该一直沿着树向下,使8 成为node 5 的子节点……对吧?
我需要帮助来正确理解插入函数。我确信我误解了它的逻辑。
谢谢(很抱歉发了这么长的帖子)!
【问题讨论】:
-
insert 函数何时决定回溯 没有回溯,只有递归遍历才能找到正确的插入节点,这里:
Node*& newChild = (p->key > key) ? p->left : p->right;。 (如果你监督它,那是一个条件运算符 - 类似于 if-else 但作为表达式。) -
@Scheff 是的,我知道函数中没有回溯,这就是我感到困惑的原因。当
insert(root, 8 ,8)被main调用时,根据insert的逻辑,8不应该成为5的右孩子吗?它如何最终成为6的正确孩子呢?这就是我不明白的。insert什么时候决定上树? -
8 最终成为 6 的(右)子节点,因为这个 "Node*& newChild = (p->key > key) ? p->left : p->right;"每次迭代您都在检查键值是否大于当前键值,然后向左移动,否则。所以这个条件让它在 6 点开始。
-
它在最后一个
else分支中结束,在那里它确定要继续的左子或右子(使用上面提到的表达式),然后它为该子指针递归调用自身。 (...直到insert()的递归调用之一没有在最后一个else分支中结束。) -
这里只是尾递归,没有回溯
标签: c++ tree insert binary-tree recursive-backtracking