我正在尝试实现二进制搜索树操作,并在删除时陷入困境。
11
/ \
10 14
使用inorder遍历作为树的表示,最初输出为10 11 14。
删除节点10,预期输出为11 14但我得到0 11 14。
删除节点14,预期输出仅为11但我得到0 11 67837.
请解释我输出错误的原因。我不是在寻找任何代码:)。
typedef struct _node{
int data;
struct _node *left;
struct _node *right;
} Node;
Node* bstree_search(Node *root, int key)
{
if(root == NULL){
return root;
}
// Based on binary search relation, key can be found in either left,
// right, or root.
if(key > root->data)
return bstree_search(root->right, key);
else if(key < root->data)
return bstree_search(root->left, key);
else
return root;
}
void bstree_insert(Node **adroot, int value)
{
// since address of address(root is itself address) is passed we can change root.
if(*adroot == NULL){
*adroot = malloc(sizeof(**adroot));
(*adroot)->data = value;
(*adroot)->right = (*adroot)->left = NULL;
return;
}
if(value > (*adroot)->data)
bstree_insert(&(*adroot)->right, value);
else
bstree_insert(&(*adroot)->left, value);
}
void bstree_inorder_walk(Node *root)
{
if(root != NULL){
bstree_inorder_walk(root->left);
printf("%d ",root->data);
bstree_inorder_walk(root->right);
}
}
void bstree_delete(Node **adnode)
{
//Node with no children or only one child
Node *node, *temp;
node = temp = *adnode;
if((*adnode)->right == NULL || (*adnode)->left == NULL){
if((*adnode)->right == NULL){
*adnode = (*adnode)->left;
}else{
*adnode = (*adnode)->right;
}
}else{ // Node with two children
}
free(temp);
}
int main()
{
Node *root = NULL;
Node *needle = NULL;
int i,elems[] = {11,10,14};
for(i = 0; i < 3; ++i)
bstree_insert(&root,elems[i]);
bstree_inorder_walk(root);
printf("\n");
needle = bstree_search(root, 10);
bstree_delete(&needle);
bstree_inorder_walk(root);
printf("\n");
needle = bstree_search(root, 14);
bstree_delete(&needle);
bstree_inorder_walk(root);
printf("\n");
}
答案 0 :(得分:6)
请解释我出错的原因 输出
您的delete
函数还必须更改已删除节点的父级。例如,当您删除包含10的节点时,必须将根Node
的{{1}}子项设置为left
。由于您不这样做,当您稍后遍历树时,您将打印出已经被释放的数据。
我没有查看除NULL
以外的任何代码,因此一旦进行此更改,我无法保证其正常工作。
答案 1 :(得分:1)
你的输出错误,因为你的删除代码有问题(好吧,也许这说明显而易见)。
要从二叉搜索树中删除,首先要找到要删除的节点。如果它是叶节点,则将其父节点中指向它的指针设置为NULL,并释放该节点。如果不是叶子节点,则选择两个叶子节点之一(右子树中最左边的子节点或左子树中最右边的子节点)并插入代替您需要删除的节点,将指向其前一个父节点中的节点的指针设置为NULL,并删除您现在“拼接”出树的节点。
答案 2 :(得分:1)
有几件事情很快,
首先,当你分配节点时,你真的应该在类型的大小(即节点)上做malloc。
其次,如果你有2个孩子,看起来你并没有真正删除节点并通过推广其中一个孩子来重建搜索树。
其他人已经遇到了其他明显错误。