I was solving this question https://leetcode.com/problems/binary-tree-pruning/description/ and came up with the solution directly below (which doesn't change the tree at all). When i debug this, it does enter the if statement - meaning it recognizes that a and b are both null for the leaf node, but when I assign root=nullptr it doesn't actually change the root (which is a leaf) to null. why doesn't my code work as it should?
TreeNode* pruneTree(TreeNode* root) {
if (root == nullptr){return nullptr;}
TreeNode *a = pruneTree(root->left);
TreeNode *b = pruneTree(root->right);
if (root->val == 0 && a==nullptr && b== nullptr){
return nullptr; // or root = nullptr, they have same effect
}
return root;
}
I am just confused on why it actually does change the value of the pointer to null when using the code below, when the only thing that is different is
root->left = pruneTree(root->left);
root->right = pruneTree(root->right);
the correct answer is:
TreeNode* pruneTree(TreeNode* root) {
if (root == nullptr){return nullptr;}
root->left = pruneTree(root->left);
root->right = pruneTree(root->right);
if (root->val == 0 && root->left == nullptr && root->right == nullptr){
return nullptr;
}
return root;
}
my guess would be that this gives us direct access to not only the spot in memory for the left and right children, but also for the root itself? (which is why we are able to "delete" it?) not really delete but just return nullptr for it.
Related
void flatten(struct Node* root)
{
// base condition- return if root is NULL or if it is a
// leaf node
if (root == NULL || root->left == NULL && root->right == NULL)
return;
// if root->left exists then we have to make it
// root->right
if (root->left != NULL) {
// move left recursively
flatten(root->left);
// store the node root->right
struct Node* tmpRight = root->right;
root->right = root->left;
root->left = NULL;
// find the position to insert the stored value
struct Node* t = root->right;
while (t->right != NULL)
t = t->right;
// insert the stored value
t->right = tmpRight;
}
// now call the same function for root->right
flatten(root->right);
}
here this is a code for flattening a tree, I realised we pass the root by value and not by reference. My doubt is, since we are changing the attributes or links of every node shouldn't we pass the root by reference? like:
Node *&root
But for some reason this code seems to work just fine, I really want to know the reason
I have tow code about the the question Binary Tree Pruning.
this is a wrong code
class Solution {
public:
TreeNode* pruneTree(TreeNode* root) {
if(root == NULL)
return NULL;
if((root->left = pruneTree(root->left)) == NULL &&
(root->right = pruneTree(root->right)) == NULL){
if(root->val == 0){
delete root;
return NULL;
}
}
return root;
}
};
this is my passed code
class Solution {
public:
TreeNode* pruneTree(TreeNode* root) {
if(root == NULL)
return NULL;
root->left = pruneTree(root->left);
root->right = pruneTree(root->right);
if(root->left == NULL && root->right == NULL){
if(root->val == 0){
delete root;
return NULL;
}
}
return root;
}
};
I want to know what cause the difference between the two programs
In the second code, it is guaranteed that both pruneTree(root->left) and pruneTree(root->right) are called, because those are two separate expressions.
root->left = pruneTree(root->left);
root->right = pruneTree(root->right);
In the first code you have:
(root->left = pruneTree(root->left)) == NULL &&
(root->right = pruneTree(root->right)) == NULL
The difference here is that pruneTree(root->left) and pruneTree(root->right) are in one expression, so they might (and this case the do) depend on each other.
If (root->left = pruneTree(root->left)) == NULL evaluates to false then the parte after the && does not need to be evaluated, because the complete expression can't become true anymore.
I'm having difficulty deleting a node in my binary search tree. The delete function is part of my Node class, and my findMin function is as well. Below is my delete function...
/**********************************************
* Delete
**********************************************/
node* node::Delete(node *root, string stuff)
{
//node *temp;
if (root == NULL) // Searches for value in tree
return NULL;
if (stuff < root->val) // String is in left subtree
root->left = Delete(root->left, stuff);
else if (stuff > root->val) // String is in right subtree
root->right = Delete(root->right, stuff);
else
{ // No children
if ((root->left == NULL) && (root->right == NULL))
{
delete(root);
root = NULL;
}
else if ((root->right == NULL) && (root->left != NULL)) // One left child node
{
node *temp = root;
root = root->left;
delete temp;
temp = NULL;
}
else if ((root->left == NULL) && (root->right!= NULL)) // One right child node
{
node *temp = root;
root = root->right;
delete temp;
temp = NULL;
}
else // Two children
{
node *temp = findMin(root->right); // Finds smallest value in right subtree
root->val = temp->val;
root->right = Delete(root->right, temp->val);
}
}
return root;
}
Below is my Destructor, which is giving me a SIGABRT (I'm using Xcode)
/**********************************************
* Destructor
**********************************************/
node::~node()
{
if (left != NULL) delete left;
if (right != NULL) delete right;
}
What my code is actually doing is not only deleting the node I intend to delete, but its child node. What could I be doing wrong? Is it an error with memory allocation? Is it an error with how I set the value to the child node?
You need to null your pointers to left and right before deleting a node.
You call:
node *temp = root;
root = root->left;
delete temp;
temp = NULL;
When you "delete temp" you are deleting a node which still points to root->left and root->right and your destructor insures they are also removed. You should instead do something like this:
node *temp = root;
root = root->left;
temp->left = NULL;
temp->right = NULL;
delete temp;
temp = NULL;
Also in your destructor you don't need to check if they are equal to null since delete already preforms this check.
I'm trying to make a remove function (without the use of recursion), that passes in the value of the node I want to remove.
My current problem is that my destructor seems to be making the program crash (getting a runtime error), which is probably because I'm not deleting the root node properly in my remove function.
The code I'm trying to use to remove the root is here:
bool BST::remove_root (int val)
{
if (val == root_->val)
{
if (root_->left == NULL && root_->right != NULL)
{
Node* temp = root_->right;
delete root_;
root_ = NULL;
size_--;
root_ = temp;
return true;
}
else if (root_->right == NULL && root_->left != NULL)
{
Node* temp = root_->left;
delete root_;
root_ = NULL;
size_--;
root_ = temp;
return true;
}
else
{
Node *curr = root_->right, *child = root_->left;
delete root_;
root_ = NULL;
size_--;
root_ = curr;
Node* temp = curr;
while (temp->left != NULL)
temp = temp->left;
temp->left = child;
return true;
}
}
}
In my code, just using val by itself is the value being passed in to the remove function (the one I want to remove). When I dereference things like root_->val, I'm accessing the val in my BST class.
I don't really understand why this wouldn't be able to continuously delete the root node (like I said I think it's the destructor making the program crash), but I feel like it could be invalid pointers?
I am getting Exception when running the BST Deletion. Below is my code snippet:
Bst::node * Bst::del(node *root, int num)
{
if (root == NULL)
{
return root;
}
else if (num < root->data)
{
root->left = del(root->left, num);
}
else if (num > root->data)
{
root->right = del(root->right, num);
}
else
{
if (root->left == NULL)
{
node * tmp = root;
root = root->right;
delete tmp;
}
else if (root->right == NULL)
{
node * tmp = root;
root = root->left;
delete tmp;
}
else if (root->left == NULL && root->right == NULL)
{
delete root;
root = NULL;
}
else
{
node *tmp = root;
tmp = findMin(root->right);
root->data = tmp->data;
root->right = del(root->right, tmp->data);
}
}
return root;
}
void Bst::del(int num)
{
del(root, num);
}
Everything works fine when I am deleting the other nodes but when I delete the root node itself then the function void Bst::del(int num) gets the garbage value from the function Bst::node * Bst::del(node *root, int num). The error gets resolved when I rewrite my function as
void Bst::del(int num)
{
root = del(root, num);
}
Question 1. Why it works when I delete the middle nodes or any other node except the root node. While debugging I found that even root was getting deleted properly when the function Bst::node * Bst::del(node *root, int num)was executing but when the call returned to the void Bst::del(int num) then the value of root was not getting retained and was garbage.
Question 2: Why the error got fixed when I stored the returned value in variable root?
While deleting a BST node using recursion, you must track the root node, which you're doing correctly as
root->left = // ... and root->right = ...
However when call reaches to caller after unwinding the stack, the root may get modified ( case when you delete the root itself )
This hopefully answers both of your questions