Could someone please let me know why my code isn't working? I am trying to count the number of times a given value appears in a binary tree using recursion. However, this approach is not working. I'd really appreciate some feedback and insight. Thank you.
public int valCount(int val) {
if (root == null) {
return 0;
}
return valCount(val, *root);
}
public int valCount(int val, Node *root) {
int cnt = 0;
if (root->left != null) {
if (root->data == val) {
cnt++;
}
int leftValCount = valCount(val, root->left);
}
if (root->right != null) {
if (root->data == val) {
cnt++;
}
int rightValCount = valCount(val, root->right);
}
return cnt + leftValCount + rightValCount;
}
A common mistake in recursion is to worry about stack frames other than the current one. Let the recursion do that work for you. Following this rule-of-thumb makes the code much easier to reason about.
The algorithm is simple: for each node, return 1 if the current node matches the target value else 0 if it doesn't and add the results of calling the same function on the left and right subtrees. The base case is when the function is called with a null root, return 0.
int valCount(int val, Node *root) {
if (!root) return 0;
return (root->val == val ? 1 : 0) +
valCount(val, root->left) +
valCount(val, root->right);
}
Related
https://practice.geeksforgeeks.org/problems/maximum-path-sum/1
this is question from geeks for geeks. i wrote my ans. but it is giving wrong. what is problem with my logic?
int path(Node *root, int & max_sum)
{
if(root==NULL)
return 0;
int l=path(root->left,max_sum);
int r=path(root->right,max_sum);
max_sum=max(max_sum,l+r+root->data);
return max(l,r)+root->data;
}
int maxPathSum(Node *root)
{
int max_sum=INT_MIN;
path(root,max_sum);
return max_sum;
// code here
}
The problem statement says
Find the maximum possible sum from one leaf node to another.
So, when you do
max_sum=max(max_sum,l+r+root->data);
You will need to check whether the root has both the children. Otherwise, they won't be considered in the final answer.
You also did
if(root==NULL) return 0;
and
max(l,r)+root->data;
These both combined are overriding a single leaf node child whose value is negative since 0 is greater than any negative integer.
So overall your code should look like this:
int path(Node *root, int & max_sum)
{
if(root==NULL) return 0;
int l=path(root->left,max_sum);
int r=path(root->right,max_sum);
if(root->left != NULL && root->right != NULL){
max_sum = max(max_sum,l + r + root->data);
}
if(root->left != NULL && root->right == NULL) return l + root->data;
if(root->right != NULL && root->left == NULL) return r + root->data;
return max(l,r) + root->data;
}
int maxPathSum(Node *root)
{
int max_sum=INT_MIN;
path(root,max_sum);
return max_sum;
}
I am implementing an AVL tree and my search and insertion functions work properly, but I get a segmentation fault with my remove function. I have implemented a BST tree correctly before, so I know the issue is with the rebalancing of the tree rather than the initial deletion of a node.
Since my insertion operation works with the rebalancing, I also know the issue is not with the rotation functions themselves.
I have tried different strategies such as maintaining a balance factor at each node and have tried implementing other source code I have found online but I always end up with a segmentation fault and really cannot find where. I'd appreciate any help.
class AVL
{
public:
AVL();
Node* insert(int num);
Node* search(int num);
Node* remove(int num);
void print();
void comparisonPrint();
private:
int comparisonCount;
Node* root;
int max(int a, int b);
int getHeight(Node* t);
int getBalance(Node* t);
Node* insert(Node* &t, int num);
Node* rotateWithLeftChild(Node* t);
Node* rotateWithRightChild(Node* t);
Node* doubleRotateWithLeftChild(Node* t);
Node* doubleRotateWithRightChild(Node* t);
Node* search(Node* t, int num);
Node* removeMin(Node* parent, Node* node);
Node* remove(Node* &t, int num);
void print(Node* t);
//print
};
int AVL::max(int a, int b)
{
return (a > b)? a : b;
}
int AVL::getHeight(Node* t)
{
return (t == NULL) ? 0 : t->height;
}
int AVL::getBalance(Node* t)
{
if(t == NULL)
return 0;
return getHeight(t->leftChild) - getHeight(t->rightChild);
}
//helper function for remove - finds min
Node* AVL::removeMin(Node* parent, Node* node) //removes node, but does not delete - returns ptr instead
{
if(node != NULL)
{
if(node->leftChild != NULL) //go to leftmost child in right subtree
return removeMin(node, node->leftChild);
else //min val
{
parent->leftChild = node->rightChild;
return node;
}
}
else //subtree empty - incorrect use of function
return NULL;
}
Node* AVL::remove(Node* &t, int num)
{
cout << num;
if(t != NULL)
{
if(num > t->key)
{
comparisonCount++;
remove(t->rightChild, num);
}
else if(num < t->key)
{
comparisonCount++;
remove(t->leftChild, num);
}
else if(t->leftChild != NULL && t->rightChild != NULL)
{
comparisonCount++;
//2 children
Node* minRightSubtree = removeMin(t, t->rightChild);
t->key = minRightSubtree->key;
delete minRightSubtree;
}
else
{
comparisonCount++;
//0 or 1 child
Node* temp = t;
if(t->leftChild != NULL)
t = t->leftChild;
else if(t->rightChild != NULL)
t = t->rightChild;
delete temp;
}
//update height
t->height = max(getHeight(t->leftChild), getHeight(t->rightChild)) + 1;
int balance = getBalance(t);
if(balance > 1 && getBalance(t->leftChild) >= 0)
return rotateWithRightChild(t);
if(balance > 1 && getBalance(t->leftChild) < 0)
{
t->leftChild = rotateWithLeftChild(t->leftChild);
return rotateWithRightChild(t);
}
if(balance < -1 && getBalance(t->rightChild) <= 0)
return rotateWithLeftChild(t);
if(balance < -1 && getBalance(t->rightChild) > 0)
{
t->rightChild = rotateWithRightChild(t->rightChild);
return rotateWithLeftChild(t);
}
}
return t;
}
So I need the remove function to remove a specified node and rebalance the tree when necessary using the appropriate rotations. However, I keep getting a segmentation fault whenever I try to call the function in my main. Thanks.
There are two problems with your code. First is the removeMin function and the else if part in remove function when the node to be deleted has two children.
Basic aim of the removeMin function should be to find the inorder successor of the node to be deleted which is t in your case. Consider the case when t has 2 children (both leaf nodes) then your removeMin function will set t->leftChild as t->rightChild->rightChild which is NULL which is wrong. Also the restructuring of the tree should be done inside remove hence removeMin becomes:
Node* AVL::removeMin(Node* node) // returns inorder successor of 't'
{
if(node->left == NULL)
return node;
return removeMin(node->left);
}
Coming to remove function, we reset t->key with minRightSubtree->key and the node to be deleted now is minRightSubtree. But notice that the order of keys has changed in the chain from node t till node minRightSubtree. t->key is less than all the keys of nodes till before minRightSubtree. Hence you cannot just delete minRightSubtree, you have to call remove function on the node minRightSubtree which will take care of restructuring this chain. Also you can get a little help from the recursion stack to get the correct child for the current node t after deletion/rotation:
Node* AVL::remove(Node* &t, int num)
{
if (t == NULL)
return NULL;
if (num > t->key)
t->rightChild = remove(t->rightChild, num);
else if (num < t->key)
t->leftChild = remove(t->leftChild, num);
else if (t->leftChild != NULL && t->rightChild != NULL)
{
//2 children
Node* minRightSubtree = removeMin(t->rightChild);
t->key = minRightSubtree->key;
t->rightChild = remove(t->rightChild, minRightSubtree->key);
}
else
{
//0 or 1 child
Node* temp = t;
if (t->leftChild != NULL)
t = t->leftChild;
else if (t->rightChild != NULL)
t = t->rightChild;
if(temp == t)
t = NULL;
delete temp;
}
if (t == NULL) // this case was added since there is a possibility of deleting 't'
return NULL;
//update height
t->height = max(getHeight(t->leftChild), getHeight(t->rightChild)) + 1;
int balance = getBalance(t);
if (balance > 1 && getBalance(t->leftChild) >= 0)
return rotateWithRightChild(t);
if (balance > 1 && getBalance(t->leftChild) < 0)
{
t->leftChild = rotateWithLeftChild(t->leftChild);
return rotateWithRightChild(t);
}
if (balance < -1 && getBalance(t->rightChild) <= 0)
return rotateWithLeftChild(t);
if (balance < -1 && getBalance(t->rightChild) > 0)
{
t->rightChild = rotateWithRightChild(t->rightChild);
return rotateWithLeftChild(t);
}
return t;
}
I'm assuming your code for updating heights and balancing the rooted sub-tree is correct since I've forgotten about it's theory and will need to revise.
I have a class for binary nodes, a binary tree, and a binary search tree, they contain your basic tree functions, like find node, add node, remove node, get height, getnumberof nodes, and others like that. I tried to add a new function that counts the number of comparisons for finding a certain a certain node in the tree, but I've confused myself. The best I was able to do is check if the node was in the tree, but I can't figure out how to have the counter increment with each comparison. The method I'm trying to do is just difficult to translate into the code I have now. I just don't think I'm doing this right. If someone could help me out with this, I'd really apreciate it.
int counter = 0;
template<class ItemType>
ItemType BinarySearchTree<ItemType>::IsInTree(BinaryNode<ItemType>*
BinTreePtr, const ItemType& item)
{
BinaryNode<ItemType>* tmp = BinTreePtr;
counter++;
if (tmp == NULL) {
printf("Number of comparisons: \n", counter);
return 1;
}
else {
counter++;
if (&tmp->getItem == item)
{
printf("Number of comparisons: \n", counter);
return 0;
}
else {
counter++;
if (item < &tmp->g)
return IsInTree(tmp->leftChildPtr, item);
else
return IsIntree(tmp->rightChildPtr, item);
}
}
}
int main(){
BinarySearchTree<string>* tree1Ptr = new BinarySearchTree<string>();
tree1Ptr->add("10");
tree1Ptr->add("20");
tree1Ptr->add("30");
tree1Ptr->add("40");
tree1Ptr->add("50");
tree1Ptr->add("60");
tree1Ptr->add("70");
tree1Ptr->add("80");
counter = 0;
tree1Ptr->IsInTree(tree1Ptr, "10");
}
Initialise the counter value to 1 and increment counter before every comparison inside the condition to if statement
if (tmp == NULL) {
printf("Number of comparisons: \n", counter-1);
return 1;
}
else {
if (counter++ && &tmp->getItem == item)
{
printf("Number of comparisons: \n", counter-1);
return 0;
}
else {
if (counter++ && item < &tmp->g)
return IsInTree(tmp->leftChildPtr, item);
else
return IsIntree(tmp->rightChildPtr, item);
}
}
counter-1 will give you the count, hope this helps
My assignment is to find the sum of all nodes on each branch in a binary search tree using recursion, and compare them to a user input value. If the user input value matches a sum of one of the branches, the function should return true.
In other words, the sum of 32+24+21+14=91. The sum of 32+24+28+25=109. The sum of 32+24+28+31=115 etc. I have tried many different methods, but cant seem to figure out how to traverse each branch accurately. So far I have only been able to traverse and find the sum of the left-most branch.
I am using the method of subtracting each node from the user input value. If the value reaches 0 at a Leaf-node, then clearly the user-input matches the node-sum of that branch on the tree.
The particular points of difficulty for me are when the branch diverges, such as at the node [24] and [28]. I clearly am getting something very simple wrong, but I cant figure it out.
Below is the condensed code I've written so far, in the form of two companion methods (also required for the assignment).
public:
bool findBranchSum1(int value) throw (InvalidTreeArgument) {
if (root == nullptr)
throw InvalidTreeArgument();
return(findBranchSum(root, value));
}
private:
bool findBranchSum(NodePtr node, int value) throw (InvalidTreeArgument)
{
bool result = false;
if (root == nullptr)
throw InvalidTreeArgument();
value -= node->getElement(); //subtract current node from user-input value.
cout << "Current Value = " << value << endl; //help track value changes
if (node->getLeftSide() == nullptr && node->getRightSide() == nullptr)
{
if (value == 0)
{
result = true;
return(true);
}
else
return(false);
}
else
{
if (node->getLeftSide() != nullptr)
{
node = node->getLeftSide(); //advance to next Left node
result = findBranchSum(node, value); //recursive call using new node
}
if (node->getRightSide() != nullptr)
{
node = node->getRightSide(); //advance to next Right node
result = findBranchSum(node, value); //recursive call using new node
}
return(result);
}
}
What am I doing wrong, and how can I fix my code to find the sum of each branch on the tree? Thank you in advance. I apologize for any errors in my format, or missing information.
This is wrong:
if (node->getLeftSide() != nullptr)
{
node = node->getLeftSide(); //advance to next Left node
result = findBranchSum(node, value); //recursive call using new node
}
if (node->getRightSide() != nullptr)
{
node = node->getRightSide(); //advance to next Right node
result = findBranchSum(node, value); //recursive call using new node
}
because you move to the left and then to the right branch of the left (node is changed by your assignment), if it exists! Change to:
if (node->getLeftSide() != nullptr)
{
result = findBranchSum(node->getLeftSide(), value);
}
if (node->getRightSide() != nullptr)
{
result = findBranchSum(node->getRightSide(), value);
}
Your return value management is also broken, change it to:
if (node->getLeftSide() != nullptr)
{
result = findBranchSum(node->getLeftSide(), value);
}
if (!result && node->getRightSide() != nullptr) // cut exploration if previous was correct...
{
result = findBranchSum(node->getRightSide(), value);
}
return result;
if you need to stop at the first correct branch.
I might try something like the following.
bool IsLeaf(Node const * node) {
return node && !node->left && !node->right;
}
bool CheckPathSum(Node const * node, int const target, int const sum_so_far) {
if (!node) return false;
int const sum = sum_so_far + node->element;
if IsLeaf(node) && (sum == target) return true;
return CheckPathSum(node->left, target, sum) ||
CheckPathSum(node->right, target, sum);
}
Call as
CheckPathSum(root, target, 0);
In Java, i tried this-
private static void branchSumsUtil(TreeNode root, List<Integer> sumArray, int runningSum) {
if (root == null){
return;
}
int newRunningSum = runningSum + root.key;
if (root.left == null && root.right == null){
sumArray.add(newRunningSum);
}
branchSumsUtil(root.left, sumArray, newRunningSum);
branchSumsUtil(root.right, sumArray, newRunningSum);
}
I am writing a method to check if a given tree is a BST using the inorder traversal method. On executing this method, I get a segfault. Can someone help me correct it?
here, maximum stores the largest value in the BST, and k is initialized to 0. The BST is assumed to have unique positive values. isNull(root) checks if the current node is a null node or not.
bool check(BstNode* root)
{
if (root->data==maximum) return true;
isNull(root);
check(root->left);
if (root->data>k)
{
k=root->data;
}
else
{
return false;
}
check(root->right);
}
Every time when you call check(root->left) and check(root->right), I suppose you need to add sth to determine the left and the right branch is null or not. In your code, you just assume that there is sth in left and right branch and call the check function. I think that's the main reason.
You shouldn't need to specify the maximum value. An elegant solution can be found here
There are two approaches you can do this.
One is top-down approach, first check if current node is valid, if so, then check two subtree. This is very intuitive. you can find the code from #lerman's post:
struct TreeNode {
int data;
TreeNode *left;
TreeNode *right;
};
bool isBST(TreeNode *node, int minData, int maxData) {
if(node == NULL) return true;
if(node->data < minData || node->data > maxData) return false;
return isBST(node->left, minData, node->data) && isBST(node->right, node->data, maxData);
}
if(isBST(root, INT_MIN, INT_MAX)) {
puts("This is a BST.");
} else {
puts("This is NOT a BST!");
}
The other way is a bottom-up approach: first check left substree then right substree and check current tree at last. below is the code for this approach.
bool isValidBST(TreeNode *root) {
int mmin, mmax;
return helper(root, mmin, mmax);
}
bool helper(TreeNode* root, int& mmin, int& mmax) {
if(!root) {
mmin = INT_MAX;
mmax = INT_MIN;
return true;
}
int leftmin, leftmax, rightmin, rightmax;
if(!helper(root->left, leftmin, leftmax))
return false;
if(!helper(root->right, rightmin, rightmax))
return false;
if(root->val > leftmax && root->val < rightmin) {
mmin = min(min(leftmin, rightmin), root->val);
mmax = max(max(leftmax, rightmax), root->val);
return true;
}
else
return false;
}
You might notice that the first approach is pre-order traversal and the second approach is post-order traversal. inorder traversal in inappropriate here because it conflicts with the definition of BST.