I need to implement this recursive function that will take a root of a BST and recursively count the number of nodes in it with two childrens, but i am not sure if my logic is correct?
My logic is:
If leaf or empty we return 0
You check if a node with two children we add one and call again on its left and right children
Else if a node doesnt have two children you call on its left and right subtrees without adding
Here is my function implementation
ps: assume everything in the BinarySearchTree class is implemented:
int count(BinarySearchTree *root )
{
if(root== nullptr)
{
return 0;
}
if(root->right != nullptr and root->left!= nullptr)
{
return 1+count(root->right)+count(root->left);
}
count(root->right);
count(root->left);
}
You need to sum up the counts even if your node doesn't have two children. Two count calls that you have after if are basically not used.
You can fix it like this:
int count(BinarySearchTree *root )
{
if (root== nullptr)
{
return 0;
}
int countForThisNode = root->right != nullptr and root->left!= nullptr;
return countForThisNode + count(root->right) + count(root->left);
}
In this case countForThisNode is 1 for the node that you want to count and 0 otherwise. All other nodes are added to the result no matter what.
I hope this is information you were asking for!
Your function has undefined behaviour because the control can be transfered to the closing brace without returning anything.
count(root->right);
count(root->left);
}
For starters as the list is not changed the parameter should have the qualifier const.
The function can be defined much simpler the following way
unsigned int count( const BinarySearchTree *root )
{
return root == nullptr ? 0
: ( root->left && root->right ) + count( root->left )
+ count( root->right );
}
An easy way to implement this function:
start from a standard enumeration of the nodes (can be prefix, infix, suffix, doesn't matter);
modify it so that at every node you increment the counter if there are two children.
Note that you need to look at the whole tree, as parts of it may be reached via single-childrened nodes.
visit(root):
if root.left != null:
visit(root.left)
if root.right != null:
visit(root.right)
becomes
visit(root):
count= root.left != null and root.right != null
if root.left != null:
count+= visit(root.left)
if root.right != null:
count+= visit(root.right)
return count
Related
I am trying to return the last node of a binary heap (implemented with pointers, not an array). Here, 'last' means the bottom-most node starting from the left in this case without two children, actually the node where I am supposed to append the new node to. The insert function will bind data to a new node for insertion, then call this function to return the last node, so I can add the new node either left of right depending on the child nodes present, or not.
The problem is that the right side of the tree is always empty, and never gets past the height after root's. Seems to stick on the leftmost side, because it reaches first the exit condition from every recursion call starting from left.
The recursive function checks first the node, returns 0 if no child, returns 1 if only left child and returns 2 in case of a node having two children. Here is the function :
template<typename T>
node<T> * heap<T>::find_insert_pos (node<T> *x, int &res) {
if(find_insert_poshelper(x, res) == 0) return x;
else if(find_insert_poshelper(x, res) == 1) return x;
else {
node<T> *a = find_insert_pos(x->left, res);
if(find_insert_poshelper(a, res) != 2) return a;
else return find_insert_pos(a, res);
node<T> *b = find_insert_pos(x->right, res);
if(find_insert_poshelper(b, res) != 2) return b;
else return find_insert_pos(b, res);
}
}
I've tried to figure it out, but insertion still goes wrong. The other functions used into insertion are more than triple checked.
(By the way, 'res' is passed by reference always in the chunk of code)
I have changed the logic behind the function. Instead of only validating for children per node, I validate now if the node evaluated had children, if it does then I validate one step further each of those children, left and right, to see if any of those grand-children have children themselves.
If they don't, I will loop this for the next level following the root level 0, jumping to level 1 and so on, until one of the children nodes does not contain two children, and returning x.left or x.right, depending the case.
-- Final edit --
Hard to think about a MRE since it was more about logic. The question was posted by someone in need of practice with recursion, and it happened. All the logic changed, even for sub-functions.
But it will be required to manually assign and narrow down until three levels are full (full meaning having two children) before calling this operation, which is checking three levels down. Having this done nicely I get a beautiful heap.
I can show an attempt to a MRE of how I implemented it to be able to find the bottom node to append a new node to, but not pure since I don't put the code from the 'insert' function, which is part iterative (first three levels) and part recursive (that was the original question, to find the parent node for the new node to insert). How the insert operation goes, I create a new node dynamically and then I search for the parent node where I need to append new data to (the iterative part starts here until the 8th node of the tree is reached, path similar to BFS), then when the position is retrieved (that is, the pointer itself), I test whether for left or right insertion, as by the rules of the heap. Starting at the 8th node, the value of the parent node is set recursively as follows :
First the recursive function itself :
node * function_a (node *x, int &res) {
node *temp = function_b (x, res);
if(temp != ptr_null) return temp;
else {
if(x->L != ptr_null) function_a (x->L, res);
if(x->R != ptr_null) function_a (x->R, res);
return temp;
}
}
A sub-function :
node * function_b (node *x, int &res) {
node *a = x->L;
node *b = x->R;
int aL = function_c (a->L, res);
int aR = function_c (a->R, res);
int bL = function_c (b->L, res);
int bL = function_c (b->R, res);
if(aL != 2) return a->L;
else if(aR != 2) return a->R;
else if(bL != 2) return b->L;
else if(bR != 2) return b->R;
else return ptr_null;
}
And another :
int & function_c (node *x, int &res) {
if(x->L == ptr_null && x.R == ptr_null) return res = 0;
else if(x->L != ptr_null && x->R == ptr_null) return res = 1;
else return res = 2;
}
Since this is checking 3 levels down from x defined (in this case from the root) in function_a, I can't make it 100% recursive that way or I will get a segmentation fault. How can I improve my algorithm ?
I was solving problem of insertion of node in a binary tree. I have the following doubts:
1) If we are inserting a node then we should return a pointer pointing to that node as then only we will be able to access the node, right?
2) Then here why are we returning root? We must return root->left or root->right accordingly, where am I wrong?
struct node* insert(struct node* root, int data)
{
if (root == NULL) //If the tree is empty, return a new,single node
return newNode(data);
else
{
//Otherwise, recur down the tree
if (data <= root->data)
root->left = insert(root->left, data);
else
root->right = insert(root->right, data);
return root;
}
}
3) Is this root which the above code returns the changed one from what it was previously due to recursion?
You misunderstand the return value.
The return value of this insert function is a pointer to the subtree that now has data inserted into it. If the passed in root was null, this is a new 1 node tree; if the passed in root is non-null, the return value is the same root.
This makes the recursion a bit simpler. We simply recurse until we run head-on into nullptr in a branch. Then the recursion stops, and the return value sets the parent's left or right node.
To create a brand new tree you type:
node* new_tree = insert(nullptr, 7);
to insert something into an existing tree you type:
existing_tree = insert(existing_tree, 7);
or equivalently
insert(existing_tree, 7);
so long as existing_tree isn't null.
This "double use" of the function (to both create and modify a tree) can confuse, but it makes the specific recursive use a tad less verbose, and makes the "empty tree is a nullptr" and "always do existing_tree = insert(existing_tree, val);" is a rule that makes the empty tree as the null tree work.
This is, however, a very C way of doing things.
A more c++ way of doing things would be:
std::unique_ptr<node> insert(std::unique_ptr<node> root, int data)
{
if (root == nullptr) //If the tree is empty, return a new,single node
return std::make_unique<node>(data);
else
{
//Otherwise, recur down the tree
if (data <= root->data)
root->left = insert(std::move(root->left), data);
else
root->right = insert(std::move(root->right), data);
return std::move(root);
}
}
where the flow of data into and out of the function is more explicit, and we assume node has a constructor that takes data.
This recursive insert should always return the very root node of the tree. Just because you read return root doesn't mean the original function call has finished executing, it just means the n'th recursion has finished. The recursive calls have all been pushed onto the stack and therefore must all be resolved before the original caller receives the returned value.
You can get back to the inserted node by doing a find for the inserted value.
I'm working on this find merge node method on hackerrank. My approach is: while both of the nodes are not null, I want to move one of the list to their next node, that's what flag variable is for. But somehow it's giving me segmentation fault? Did I accidentally access a null variable? Someone please enlighten me. Below is my method code.
Constraint: Both lists will converge and both lists are non-NULL
int FindMergeNode(Node *headA, Node *headB)
{
// Complete this function
// Do not write the main method.
bool flag = true;
while(headA != headB){
if(flag) headA=headA->next;
else headB=headB->next;
flag = !flag;
}
return headA->data; //or headB->data;
}
You make two assumptions:
1. There exists such node.
2. The distance of this node from the beginning of each list differs by at most 1 between the two lists. You alternately move forward in one list and then check to see if you got to the same node (by address). so if list1 has no nodes before the one you are looking for, and list2 has 2 nodes before it, you won't find a match.
If I understand your question correctly, the truth is that the distance from the end of the list is the same (because their tails are the same).
Why to use flag directly use the condition to check if it is the last node
if(headA->next ==NULL)
headA=headA->next;
else if (headB->next== NULL )
headB=headB->next;
Complete solution would be something
int FindMergeNode(Node *headA, Node *headB) {
Node *currentA = headA;
Node *currentB = headB;
//Do till the two nodes are the same
while(currentA != currentB){
//If you reached the end of one list start at the beginning of the other one
//currentA
if(currentA->next == NULL){
currentA = headB;
}else{
currentA = currentA->next;
}
//currentB
if(currentB->next == NULL){
currentB = headA;
}else{
currentB = currentB->next;
}
}
return currentB->data;
}
I'm working on a function to find the height of a binary search tree. I found a method that seems like it should work, but I keep getting this error, and I don't know whats wrong with it: Unhandled exception at 0x00903417 in PA5.exe: 0xC0000005: Access violation reading location 0x00000004.
Here are my height functions...
template <class T>
int BST<T>::height()
{
return displayHeight(mRootNode);
}
template <class T>
int BST<T>::displayHeight(BST<T> *node)
{
if (node = NULL)
{
return 0;
}
int left = displayHeight(node->mLeft);
int right = displayHeight(node->mRight);
if (left > right)
return 1 + left;
else
return 1 + right;
}
This is the implementation in the main function...
cout << endl << "height: " << tree.height();
If I should include anything else, let me know. Thanks!
if (node = NULL)
should be
if (node == NULL)
because in C++ = is an assignment operator and == is the relational operator for comparison.
Why the crash?
When you do if (node = NULL), you are assigning NULL to node and since NULL is 0 the if condition fails. So you go ahead and call the function recursively on the nodes's children. Now suppose node was actually NULL when the function was called for the first time, you'll be doing the recursive calls on NULL's left and right children!!! Leading to crash.
You are assigning null to your node parameter variable in your if statement.
if (node = NULL)
{
return 0;
}
should be
if(node == NULL) ...
Method to find the height while creating a tree(BST):For both left subtree and right subtree::
Put the elements you want to put in your binary tree in an array before you create the actual tree.
Calculate the number of elements which are greater than the root, which will be going to the left of the tree and similarly with the right side.
Then while you add the elements to your tree. Everytime set a flag bit to 1 or 0 depending on whether you are adding it to the left subtree or the right.
if(root->right && flagleft==1)
no_left--;
else if(root->right && flagright==1)
no_right--;
This is while you append a node to the left side.
if(root->left && flagl==1)
nl--;
else if(root->left && flagr==1)
nr--;
This is while you append a node to the right side.
This is because you've assigned the node to NULL i.e NULL value is 0 , so condition fails.
do if(node==NULL)
instead of
if(node=NULL)
I've been trying to implement a delete function for a Binary Search Tree but haven't been able to get it to work in all cases.
This is my latest attempt:
Node* RBT::BST_remove(int c)
{
Node* t = get_node(c);
Node* temp = t;
if(t->get_left() == empty)
*t = *t->get_left();
else if(t->get_right() == empty)
*t = *t->get_right();
else if((t->get_left() != empty) && (t->get_right() != empty))
{
Node* node = new Node(t->get_data(), t->get_parent(), t->get_colour(), t->get_left(), t->get_right());
*t = *node;
}
return temp;
}
Node* RBT::get_node(int c)
{
Node* pos = root;
while(pos != empty)
{
if(c < pos->get_data())
pos = pos->get_left();
else if(c == pos->get_data())
return pos;
else
pos = pos->get_right();
}
return NULL;
}
t is a node and empty is just a node with nothing in it.
I'm just trying to swap the values but I'm getting a runtime error. Any ideas?
edit: I'm returning temp to delete it afterwards.
Thanks
First, your last else if conditional clause is redundant. Swap it with an else clause.
Secondly, I think it would make things easier for you if you'd take as parameter a pointer to the node to remove. You can write a find() function which would find a node given its key. I'm assuming of course that you can change the function signature. If you can take as parameter the node to remove you can focus on removing the node rather than add logic for finding the node. Otherwise, still write that find() function and use that for getting the pointer to the relevant node.
When you remove a node in a binary search tree you must maintain the ordering so the tree doesn't lose its integrity. Recall that there is a specific ordering in the tree that supports the fast retrieval of elements. So, enumerate the possible cases:
The node to delete has no children. That's easy: just release its resources and you're done.
The node has a single child node. That's fairly simple too. Release the node and replace it with its child, so the child holds the removed node's place in the tree.
The node has two children. Let's call the node D. Find the right-most child of D's left subtree. Let's call this node R. Assign the value of R to D, and delete R (as described in this algorithm). Notice that R can have zero or one children.
The third scenario, illustrated:
.
.
.
/
D
/ \
/\ .
/ \
/ \
+------+
\
R
/
?