的一个错误是,如果一个人要删除左树中的节点,那么最后几行可能无法正常工作,因为它们不是对称的。所以,让我们说,树的根目录为6,左边的孩子为4,右边的孩子为8.现在,你想删除4.因此,当你在第一个while子句中找到节点后, “if(val> f-> data){”的else子句。此时,f将指向6,target和help将指向4.现在,您将f的左侧设置为target的右侧,所以6的左侧将指向NULL,f本身将指向NULL。到现在为止还挺好!但是,一旦你进入while循环,因为帮助没有正确的节点,帮助将继续指向6.最后,你做出正确的节点f(btw,此时f已经为NULL)来帮助和你会最终崩溃!
while (help->right)
help = help->right;
if (help->left)
help = help->left;
f->right = help;
另一个错误是,您不更新根指针,因此最终会删除根节点。
一种更简单的方法是将其分成三种情况。我为这三种情况提供了代码。对这三种情况分别使用一个样本树,然后对其进行调试/测试。首先,如果找到的节点(您的文件while循环正在执行)没有子节点,则将其删除并将其父项设置为NULL,然后完成操作。这是第一种情况的一个粗略的一切:
/* If the node has no children */
if (!help->left && !help->right) {
printf("Deleting a leaf node \n");
f = help->parent;
if (f) {
if (value > f->value)
f->right = NULL;
else
f->left = NULL;
}
/* If deleting the root itself */
if (f->value == root) {
root = NULL;
}
free(help);
return 0;
}
其次,如果发现节点具有唯一的孩子(左或右),然后拼接出来,并找到节点的孩子成为了兴田孩子父节点。这是第二种情况:
/* If the node has only one child node */
if ((help->left && !help->right)
|| (!help->left && help->right)) {
printf("Deleting a node with only one child \n");
f = help->parent;
if (help->left) {
child_node = help->left;
} else {
child_node = help->right;
}
if (f) {
if (value > f->value) {
f->right = child_node;
} else {
f->left = child_node;
}
} else {
/* This must be the root */
root = child_node;
}
free(help);
return 0;
}
第三种情况是有难度的 - 在这里找到的节点具有两个子节点。在这种情况下,您需要找到节点的后继节点,然后将找到的节点的值替换为后继节点,然后删除后继节点。这里是第三种情况:
/* If the node has both children */
if (help->left && help->right) {
successor_found = find_successor(help, help->data);
printf("Deleting a node with both children \n");
if (successor_found) {
successor_value = successor_found->value;
del(successor_found->value);
help->value = successor_value;
}
return 0;
}
而且,在这里被发现的代码接班人:
binary_node_t *node find_successor(binary_node_t *node, int value) {
binary_node_t *node_found;
if (!node) {return NULL; }
node_found = node;
old_data = node->data;
/* If the node has a right sub-tree, get the min from the right sub-tree */
if (node->right != NULL) {
node = node->right;
while (node) {
node_found = node;
node = node->left;
}
return node_found;
}
/* If no right sub-tree, get the min from one of its ancestors */
while (node && node->data <= old_data) {
node = node->parent;
}
return (node);
}
你应该总是上传错误消息和根据你的错误的事情,以帮助别人来帮助你。 –
同意@Uchia。事实上,您可能应该将代码粘贴到您构建的位置并将值插入树中。这样,测试代码会更容易。 –
在本页面的相关列表中,有一个相关的问题与这个问题有关。我现在很难选择一个作为重复名单。 [这一个显示一些承诺](http://stackoverflow.com/questions/7606185/deletion-in-binary-search-tree) – WhozCraig