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);
}
Related
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);
}
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 written a function that returns true if given binary tree is binary search tree else returns false.
bool IsBst(node* root)
{
if(root->left == NULL && root->right == NULL)
{
return true;
}
if(root->left->data <= root->data && root->right->data > root->data)
{
return (IsBst(root->left) && IsBst(root->right))
}
else
{
else false;
}
}
Is my function right?
Will this function return right answer?
I have doubt in case of if left child is null then what will this comparison root->left->data<=root->data return?(If there is NULL)
Help me to improve this!
Thanks in advance!
It should be something like
bool IsBst(const node* root, node* minNode = nullptr, node* maxNode = nullptr)
{
if (root == nullptr) {
return true;
}
if (minNode != nullptr && root->data < minNode->data)
{
return false;
}
if (maxNode != nullptr && maxNode->data < root->data)
{
return false;
}
return IsBst(root->left, minNode, root)
&& IsBst(root->right, root, maxNode);
}
If you're using C++ 17 and above, you can do it even more elegantly by using an optional class. Hence, you don't need to do nullptr checks for min and max:
bool checkBST0(const Node* root, const std::optional<int>& min, const std::optional<int>& max) {
if (root != nullptr) {
const auto data = root->data;
if ((min.has_value() && min >= data) ||
(max.has_value() && max <= data)) {
return false;
}
std::optional<int> opt(data);
return checkBST0(root->left, min, opt) && checkBST0(root->right, opt, max);
}
return true;
}
Initially, you should call this method with an optional without any value:
std::optional<int> emptyOptional;
return checkBST0(root, emptyOptional, emptyOptional);
Nope, it's not right. It would fail on this tree:
3
\
\
5
And it would give a wrong answer on this one:
4
/ \
/ \
/ \
2 6
/ \ / \
1 9 0 8
A BST is defined as a tree, whose each internal node stores a key greater than all the keys in the node’s left subtree and less than those in its right subtree (see the Wikipedia article).
So it's not enough for a 1-2-9 left subtree in my example to have a left node value less than it's root (1<2) and the right node greater than it (9>2). It should also satisfy the condition that all its nodes have values less than 4, the value in the whole tree's root.
Here is an example in C I gave in the answer to the question Pseudo code to check if binary tree is a binary search tree - not sure about the recursion:
// Test a node against its closest left-side and right-side ancestors
boolean isNodeBST(NODE *lt, NODE *node, NODE *rt)
{
if(node == NULL)
return true;
if(lt != NULL && node->key <= lt->key)
return false;
if(rt != NULL && node->key >= rt->key)
return false;
return
isNodeBST(lt, node->left, node) &&
isNodeBST(node, node->right, rt);
}
boolean isTreeBST(TREE *tree)
{
return isNodeBST( NULL, tree->root, NULL);
}
The user inputs values of int age, and the function is supposed to accept parameters from a pointer to the head of the list,
and go through the linked list nodes and return the highest value of int age.
Heres my function; I keep getting random numbers as the output:
int findLargest (StudentCard *p) {
int current = p->age;
int next;
StudentCard *temp = p;
while(temp != NULL){
if (p->age == NULL) {
//The value at this node is obviously larger than a non-existent value
return current;
} else {
//Recur to find the highest value from the rest of the LinkedList
next = findLargest(p->next);
}
//Return the highest value between this node and the end of the list
if (current > next) {
return current;
} else {
return next;
}
temp=temp->next;
}
}
You're mixing iteration with recursion, which is usually not a good idea.
(Your compiler should have warned about possibly not returning a value from the function. )
You're also possibly dereferencing a null pointer here:
int current = p->age;
and comparing the wrong thing here:
if (p->age == NULL)
(The fact that the program doesn't crash makes me suspect that you have an object with zero age somewhere, causing you to return that zero instead of recursing.)
If you read the loop carefully, you'll notice that it always returns a value on the first iteration, so temp is never advanced, and the while could be replaced with if.
You should rewrite the function to be either iterative or recursive.
An iterative solution would look like this:
int findLargest (StudentCard *p)
{
int current = std::numeric_limits<int>::min();
while (p != NULL){
if (p->age > current) {
current = p->age;
}
p = p->next;
}
return current;
}
and a recursive solution would look like this:
int findLargest (StudentCard *p)
{
if (p == NULL) {
return std::numeric_limits<int>::min();
}
return std::max(p->age, findLargest(p->next));
}
First of all, you should return -1 at the end of your function to inform that nothing was found.
Then secondly, you are sending the p->next as the parameter of findLargest function without checking NULL in following code:
//Recur to find the highest value from the rest of the LinkedList
next = findLargest(p->next);
And also, when you are using recursion function call, you don't need the while(temp != NULL) loop at all. You could replace the while with a if and remove the temp = temp->next; statement. Either recursion or iteration is enough for solving your problem.
Your findLargest function should be as following code:
int findLargest (StudentCard *p)
{
if (p != NULL)
{
int current = p->age;
int next = findLargest(p->next);
if (current > next) {
return current;
}
else {
return next;
}
}
return -1;
}
For getting the oldest student node pointer, use following definition:
StudentCard * findLargestNode(StudentCard *p)
{
if (p != NULL)
{
int curAge = p->age;
StudentCard *next = findLargestNode(p->next);
if (next && (next->age > curAge)) {
return next;
}
else {
return p;
}
}
return NULL;
}
And for printing the oldest student ID, use the function as following
{
StudentCard *pOld = findLargestNode(listHead); // `listHead` is HEAD node of your link-list
if ( pOld )
cout << pOld->id << endl;
}
I'm working on an AVL tree. It seems the my remove only works correctly some of the time. I built a tree that looks like this
f
/ \
e j
/ / \
a h s
by inserting in the order f e h s j a. I know that it is working correctly on insert and balancing.
When I remove a, or j, or h, or s, or e, everything works fine. If I remove f, then it replaces f with h, which is correct, but I lose j and s.
This is the first function that is called.
void remove(const ItemType& item)
{
if(root == NULL)
return;
else
{
remove(root, item);
}
};
The first function calls this one to recursively find the correct node.
void remove(Node<ItemType>* & node, const ItemType& item)
{
if(item > node->item)
{
if (node->rightChild == NULL)
{
return; // there is nothing here to remove
}
else
{
// recurse to next node
remove(node->rightChild, item);
}
}
else if (item < node->item)
{
if (node->leftChild == NULL)
{
return; // there is nothing here to remove
}
else
{
// recurse to next node
remove(node->leftChild, item);
}
}
else if (node->item == item)
{
remove(node);
}
if (node != NULL)
node->updateHeight();
};
This is the last function to be called. This is where the deletion and swaps are done.
void remove(Node<ItemType>* & node)
{
if (node->rightChild == NULL && node->leftChild == NULL)
{
delete node;
node = NULL;
}
else if (node->rightChild == NULL)
{
Node<ItemType>* temp = node;
node = node->leftChild;
delete temp;
}
else
{
Node<ItemType>* & temp = node->rightChild;
while (temp->leftChild != NULL)
temp = temp->leftChild;
node->item = temp->item;
delete temp;
temp = NULL;
}
if(node != NULL)
node->initializeHeight();
};
I am wondering if it has something to do with the lines
Node<ItemType>* & temp = node->rightChild;
while (temp->leftChild != NULL)
temp = temp->leftChild;
node->item = temp->item;
delete temp;
temp = NULL;
and the temp pointer is acting in a behavior I am not familiar with, or if my whole implementation is wrong. I know the missing nodes are out there somewhere because my memory leak shows me those two nodes that go missing are never deleted.
I am wondering if it has something to do with the lines
Yes. Node<ItemType>* & temp = node->rightChild; says temp is an alias for node->rightChild. So the while loop modifies node->rightChild and you lose the handle to the original right child.
Take an ordinary pointer and walk it down the right subtree until you have gotten to the parent of its smallest member. Then get the value of the smallest member to copy it into node->item, and delete the parent's left child.