Reputation: 4028
I haven't done pointer arithmetic in a long time, so I figured I'd try my hand at C and do a simple Binary Search Tree. I can't get the hang of deletion, however. Something along these lines works as I expect:
typedef struct Node{
int value;
struct Node *left;
struct Node *right;
}Node;
typedef struct Tree{
struct Node* root;
}Tree;
int main(){
Tree *tree = createTree();
treeInsert(10, tree); // Inserts 10 at root
treeInsert(30, tree); // Inserts 30 to root->right
treeInsert(5, tree); // Inserts 5 to root->left
treeInsert(7, tree); // Inserts 7 to root->left->right
treeInsert(12, tree); // Inserts 12 to root->right->left
// Removes Node "7" from the tree successfully
free(tree->root->left->right); // Free memory for this node in the tree
tree->root->left->right = NULL; // Set the pointer to NULL
return 0;
}
I'd like to write a nodeDelete(Node *killNode)
function to free the memory associated with a node, then point it to NULL, but I find it doesn't work like I expect it to.
int main(){
// ... snip ...
Node *kill = tree->root->left->right // Points kill node to Node "7"
free(kill); // Deallocates memory
kill = NULL; // Points kill to NULL, but keeps
// tree->root->left->right **undefined**
// ... snip ...
}
I think my problem is that I'm telling it that kill
now points to NULL, which disconnects it from the node in the tree and doesn't effect the original node pointer. How can I tell it that I want to point tree->root->left->right
to NULL instead of kill
? Do I need a pointer-to-a-pointer in this case?
Upvotes: 1
Views: 1096
Reputation: 24140
Yes, you need to use a double pointer. You'll also want to make sure you recursively delete any children of the node you're deleting:
void nodeDelete(Node **killNode)
{
if(!*killNode)
return;
// Free child nodes
nodeDelete((*killNode)->left);
nodeDelete((*killNode)->right);
// Free the node itself
free(*killNode);
*killNode=NULL;
}
The null-pointer check is intentionally performed right at the beginning -- this prevents you from having to wrap the recursive calls in null-pointer check.
Upvotes: 0
Reputation: 239011
Yes, if you want to delete that node you need to set tree->root->left->right
to NULL
. This means that you can't just pass the value of that pointer to the deletion function.
You have two options: you can either pass a pointer to the parent of the node to be deleted, along with information about which child to delete:
nodeDelete(Node *parent, int kill_right)
{
Node *kill;
if (kill_right) {
kill = parent->right;
parent->right = NULL;
} else {
kill = parent->left;
parent->left = NULL;
}
free(kill);
}
In this case you'd call nodeDelete(tree->root->left, 1);
.
Alternatively you can pass a pointer to the pointer that you want to remove:
nodeDelete(Node **killptr)
{
free(*killptr);
*killptr = NULL;
}
In this case you'd call nodeDelete(&tree->root->left->right);
.
Upvotes: 2