我正在为课程设计二进制搜索树分配,为此功能,我需要遵循教授的伪代码。不幸的是,我不确定一个具体细节,她拒绝澄清。
链接到伪代码在这里: https://imgur.com/a/rhjhEIa
SUBROUTINE insert(current, parent, node)
IF current is null
IF parent is null
root = node
ELSE
ID node.value < parent.value
parent.left = node
ELSE
parent.right = node
END IF
RETURN true
END IF
ELSE IF node.value = current.=value
RETURN false
ELSE IF ode.value < current.value
insert(current.left, current, node)
ELSE
insert(current.right, current, node)
END IF
END SUBROUTINE
代替node
,我似乎尝试了大多数允许的变量,包括当前变量,父变量(甚至是无效的值,令人震惊。)
bool recursiveInsert(Node* current, Node* parent, double value)
{
if (current == NULL)
{
if (parent == NULL)
{
}
else
{
if (current->value < parent->value)
{
parent->left = current;
}
else
{
parent->right = current;
}
return true;
}
}
else if(parent->value == current->value)
{
return false;
}
else if (parent->value < current->value)
{
insert(current->left, current->value, current);
}
else
{
insert(current->right, current->value, current);
}
}
我希望输出将值添加到二叉搜索树中并返回true,但是当我到达需要“节点”的部件时,程序当前只会抛出错误。
答案 0 :(得分:1)
正如您已经提到的,这是在二进制搜索树中插入节点的功能。参数如下
parent
是被检查节点的父节点。这将用树的根来调用。 current
是要检查的父节点的左侧或右侧。首次调用该函数时,如果当前节点的值小于根,则应使用root->left
,如果该值大于root->right
,则应使用root
。如果root
为空,则current
也应为NULL
if (root == NULL)
{
ret = recursiveInsert(NULL, NULL, node);
}
else if (root->value < node->value)
{
ret = recursiveInsert(root->left, root, node);
}
else if (root-> value > node->value)
{
ret = recursiveInsert(root->right, root, node);
}
else
{
//same value, handle error
}
node
是要添加到树中的新节点。应该在调用recursiveinsert
之前完成该节点的内存分配,并指定值。
现在,让我们看看您编写的代码。
第一个错误是将第三个参数设为double
。这应该是类型node
的参数,该参数之前应该已经分配过。
从条件检查来看
ELSE IF node.value = current.=value
RETURN false
似乎node->value
是整数类型。
考虑到所有这些,更新的代码如下。
Node* root = NULL; //global variable
...
bool recursiveInsert(Node* current, Node* parent, Node* node)
{
if (current == NULL)
{
if (parent == NULL)
{
root = node;
}
else
{
if (current->value < parent->value)
{
parent->left = node;
}
else
{
parent->right = node;
}
return true;
}
}
else if(node->value == current->value)
{
return false;
}
else if (parent->value < current->value)
{
recursiveInsert(current->left, current, node);
}
else
{
recursiveInsert(current->right, current, node);
}
}
答案 1 :(得分:1)
node
是先前分配的节点,其中包含要插入树中的数据。最初的调用者分配它(这是毫无意义的,并且在RW代码中从来没有完成过)。实际上,除非您考虑使用一个可能将 个节点移出的库,否则实际上不太可能实际执行此模式。一棵树变成另一棵树,而您想避免建立/删除节点本身的开销。
关于算法,它相当简单,尽管不是很漂亮:
如果current
和parent
都为空,则意味着这必须是某个全局指针root
所跟踪的树中的第一个节点。因此,root
被直接分配了传入节点。
否则,如果current
为空,但parent
不是 ,则意味着parent
是树中的某个潜在叶子(这意味着它具有向左,向右或同时包含都为null的指针),那么您已经落在了null指针上。插入操作需要与父值进行比较,以了解您是将节点挂在左侧还是右侧。请注意,这是低效率的,因为您已经进行了比较(这是您首先到达此处的方式)。
否则,如果current
不为空,我们只需检查值是否等于或小于(如果两个都不为真,则假定更大),然后驱动到left或right的子树中保证。在这种情况下,current.left
或current.right
成为递归的current
,而current
成为上述递归调用的parent
。
就是这样。这就是该算法的工作方式。坦率地说,这是微不足道的。
要通过您的参数列表(需要一个值而不是最后一个参数的节点)来实现该算法,只需确保仅在实际挂起节点时才分配节点,并且仅要然后(有两种情况。
bool recursiveInsert(Node* current, Node* parent, double value)
{
bool result = false;
if (current == NULL)
{
if (parent == NULL)
{
root = malloc(sizeof *root);
root->value = value;
root->left = root->right = NULL;
}
else
{
Node *p = malloc(sizeof *p);
p->value = value;
p->left = p->right = NULL;
if (value < parent->value)
{
parent->left = p;
}
else
{
parent->right = p;
}
result = true;
}
}
else if (value < parent->value)
result = recursiveInsert(current->left, current, value);
else if (parent->value < value)
result = recursiveInsert(current->right, current, value);
return result;
}
在树中插入一个值时,调用将看起来像这样:
recursiveInsert(root, NULL, value);
虽然不漂亮,但是可以。它依赖于全局root
存在可能是该算法最糟糕的部分。多重比较可能在yuck列表中排名第二。
理想情况下,将树的根作为参数传递。此外,我们可以使算法像现在这样递归,但不再依赖某些全局root
。最后,我们可以将参数计数减少为两个:指针的地址(最初是根指针的地址),以及要插入的值。不管树是否使用递归,将指针指向指针作为树访问方法使该算法更加优雅。两者都在下面提供:
bool treeInsert(Node **pp, double value)
{
bool result = false;
if (!*pp)
{
*pp = malloc(sizeof **pp);
(*pp)->value = value;
(*pp)->left = (*pp)->right = NULL;
result = true;
}
else if (value < (*pp)->value)
{
result = recursiveInsert(&(*pp)->left, value);
}
else if ((*pp)->value < value)
{
result = recursiveInsert(&(*pp)->right, value);
}
return result;
}
bool treeInsert(Node **pp, double value)
{
bool result = false;
while (*pp)
{
if (value < (*pp)->value)
pp = &(*pp)->left;
else if ((*pp)->value < value)
pp = &(*pp)->right;
else break;
}
if (!*pp)
{
*pp = malloc(sizeof **pp);
(*pp)->value = value;
(*pp)->left = (*pp)->right = NULL;
result = true;
}
return result;
}
无论哪种情况,您都通过传递根指针(因此是指向指针的指针)的地址来调用,其中空尝试由NULL根表示:
treeInsert(&root, value);
这两个功能都可以完成手头的任务。我将错误强化作为一项任务留给您(检查您的malloc)。