BST; the sum of BST elements which are greater then the sum of their direct children - c

So the task is to write a function which returns the sum of BST elements which are greater then the sum of their direct children. Do not count leaf nodes. I did it this way, the base case when the tree is empty return 0, and if it doesn't have sons also return 0. Then I checked if node has one or two children and the condition for the sums.
int sum(struct node* root)
{
if (root== NULL) return 0;
if (root->right == NULL && root->left==NULL) return 0;
if (root->right!= NULL && root->left != NULL)
{
if (((root->right)->key + (root->left)->key) < root->key) return root->key;
}
if (root->right != NULL && root->left==NULL)
{
if ((root->right)->key< root->key) return root->key;
}
if (root->left != NULL && root->right==NULL)
{
if ((root->left)->key < root->key) return root->key;
}
else return sum(root->right) + sum(root->left);
}
Main:
struct node* root = NULL;
add(&root,-4);
add(&root,6);
add(&root,8);
add(&root,-11);
add(&root,5);
add(&root,7);
add(&root,-20);
printf("%d",sum(root));
It should return -1 (6+8-11-4), but my function doesn't work I don't know why.

In your code, the else clause will never be executed; your previous conditions have dealt with all possibilities.
However, the expression should be executed. You either need to add + sum(root->left) + sum(root->right) as part of the three non-degenerate return statements, or you need to save the root->key in a local variable (defaulting to zero) and fall through to return return_value + sum(root->left) + sum(root->right);.
Hence (using the abbreviation rv for 'return value':
int sum(struct node* root)
{
int rv = 0;
if (root == NULL || (root->right == NULL && root->left == NULL))
return rv;
if (root->right != NULL && root->left != NULL)
{
if ((root->right->key + root->left->key) < root->key)
rv = root->key;
}
if (root->right != NULL && root->left == NULL)
{
if (root->right->key < root->key)
rv = root->key;
}
if (root->left != NULL && root->right == NULL)
{
if (root->left->key < root->key)
rv = root->key;
}
return rv + sum(root->right) + sum(root->left);
}
Warning: pristine code, unsullied by any attempt to compile it.
You could use an else if chain for the last three 'outer' if tests (with an else clause instead of the last test) to avoid repeated tests. Whether there'd be a measurable difference is debatable; an optimizer might even make the change for itself.

Related

The least node that is greater than or equal to a given value in AVL

I am trying to implement a function in C that will find the smallest int that is greater than or equal to a given int in an AVL. For example:
if I have an AVL tree consisting of 1,2,3,4,5,6,7 and I put in 6, it should return 6.
if I have an AVL tree consisting of 1,2,3,4,6,7 and I put in 5, it should return 6.
if none are found, return -1.
I have found a case (there could be more) where this implementation fails. If I have an AVL tree of 1,2,3,4,5,6,7 and I input 3 it incorrectly returns 4. This case occurs when the ROOT is bigger than the input. I am not sure how to fix this though. There could also be other cases — if you could let me know that would be great.
Here is my attempt:
int findLeastGreatest(Node *root, int input) {
// Never found
if (root->left == NULL && root->right == NULL && root->data < input)
return -1;
// Found
if ((root->data >= input && root->left == NULL) ||
(root->data >= input && root->left->data < input))
return root->data;
if (root->data <= input)
return findLeastGreatest(root->right, input);
else
return findLeastGreatest(root->left, input);
}
Your function has problems: you are testing too many conditions together:
Here is a simpler approach:
if the root is NULL, you should return -1;
if the root->data < input, you should just recurse on the root->right node
if root->data == input you should just return input.
otherwise, you should recurse on the left node and return the result if found, otherwise return root->data.
Here is an implementation:
int findLeastGreatest(const Node *root, int input) {
if (!root)
return -1;
if (root->data < input)
return findLeastGreatest(root->right, input);
if (root->data == input)
return input;
int value = findLeastGreatest(root->left, input);
if (value == -1)
return root->data;
else
return value;
}
If you are not required to produce a recursive version, here is a simpler version with a while loop:
int findLeastGreatest(const Node *root, int input) {
int value = -1;
while (root) {
if (root->data < input) {
root = root->right;
} else {
value = root->data;
root = root->left;
}
}
return value;
}
I find it easier to write this function in a loop. The algorithm in the pseudocode below should work. The key idea is to not assign to bound unless the condition (node.key >= key) is true, in which case you must also traverse left to look for potentially smaller keys that satisfy the same condition. Otherwise, traverse right to look for larger keys that might satisfy.
least_greatest(node, key):
bound = -1
while node != NULL:
if node.key >= key:
bound = node.key # found a bound, but it might not be the least bound
node = node.left # look for a smaller key
else:
node = node.right # look for larger keys
return bound
P.S. this function is called upper_bound in the C++ STL, and I've also seen this called "least upper bound".

Faulty function that finds a node in a binary tree

There is something wrong with this function. It's supposed to find a node with the same value phone. I believe it's got problems when it tries to find a node that that doesn't exist.
Here it is:
bst_node* find_node(bstree* bst, unsigned long phone) {
bst_node* x = bst->root;
if(x == NULL)
return NULL;
if(x->phone == phone)
return bst->root;
while (x->phone != phone && (x->left != NULL && x->right != NULL) ) {
if(phone <= x->phone) {
x = x->left;
} else {
x = x->right;
}
}
if (x->phone == phone) {
return x;
} else {
return NULL;
}
}
Basically your problem was in your while loop. Remember that you can't guarantee that every node will have two children, some nodes may only have one child and you were not exploring those nodes that only had one child. What I do below is separate out the check for the left and right node existence into the conditionals within the while loop. This lets us explore the whole tree :) I also added in an else statement within the while loop because if the node has no children then we have finished exploring and there is no way the node can be in the tree.
bst_node* find_node(bstree* bst, unsigned long phone) {
bst_node* x = bst->root;
if(x == NULL)
return NULL;
if(x->phone == phone)
return bst->root;
while (x->phone != phone){
if(phone <= x->phone && x->left != NULL){
x = x->left;
}
else if (phone > x->phone && x->right != NULL){
x = x->right;
}
else {return NULL;}
return x;
}

Binary search tree insertion (C)

Thanks, now for some reason it's not working as intended. When I run the program it just gives an error "bst.exe has stopped working" and it happens in this function.
static NODE *insert_i(NODE *r, int x)
{
NODE *leaf;
while(r)
{
if(r->val == x)
return r;
if(x < r->val && r->left != NULL)
r = r->left;
else if(x > r->val && r->right != NULL)
r = r->right;
}
leaf = malloc(sizeof(NODE));
leaf->left = NULL;
leaf->right = NULL;
leaf->val = x;
count++;
if(x < r->val)
r->left = leaf;
else
r->right = leaf;
return r;
}
void bst_insert(BST_PTR t, int x)
{
t->root = insert_i(t->root, x);
}
You have
while(r)
{
if(r == NULL)
The if condition will never be true, as if r is NULL then the loop will end, without returning anything from the function.
What will happen if you while loop is not entered or exited without returning? It will not return anything and behaviour will be undefined.
So, return NULL to indicate that not found or move if(r==NULL) out of the loop. It will not be executed inside the loop.

Binary Search Tree in C: remove node function

I'm putting together functions for a binary search tree and ran into a wall. I'm working on each situation that might be encountered when a node holding a specified value needs to be removed from the tree. I'm uncertain how to handle freeing the node if it does not have a left and right child. The function must return a node. Do I back up, examine each left and right child, and remove the value while it's in a child? But then if the value is in the root, wouldn't I have a similar problem with how to remove it? Just by way of explanation, the program uses a void pointer then casts the TYPE val in a separate function compare() which evaluates both values and returns -1 for <, 0 for ==, and 1 for >.
struct Node *_removeNode(struct Node *cur, TYPE val)
{
if (compare(cur->val, val) == 0) { //if val == cur->val
if (cur->right != NULL && cur->left != NULL) { //if cur has right and left
cur = _leftMost(cur->right);
free(_leftMost(cur->right));
}
else if (cur->right == NULL && cur->left != NULL) { //if cur has left
cur = cur->left;
free(cur->left);
}
else if (cur->right != NULL && cur->left == NULL){ //if cur has right
cur = cur->right;
free(cur->right);
}
else if (cur->right == NULL && cur->left == NULL){ //if cur has no child
//free cur if cur = val
}
}
else if (compare(cur->val, val) == -1) {
cur->right = _removeNode(cur->right, val);
}
else if (compare(cur->val, val) == 1) {
cur->left = _removeNode(cur->left, val);
}
return cur;
}
If the node has neither child then it can simply be deleted. In order to make your recursion in the other cases work, you should return NULL from _removeNode. In all cases, cur should be deleted (freed) as it is no longer needed. In each case, you need to return the replacement subtree. The complication occurs in the first case where the left most descendent of the right child is pulled up. After pulling it up, you need to remove it from the right sub-tree (note that it may be the right sub-tree).
I wrote all of the below off the top of my head so be prepared for a few errors/a bit of debugging. Also, _leftMost and _removeLeftMost can be merged with a bit of work.
The block in question should look something like:
Node *replacement;
if (cur->right != NULL && cur->left != NULL) { //if cur has right and left
replacement = _leftMost(cur->right);
replacement->right = _removeLeftMost(cur->right,replacement);
replacement->left = cur->left;
}
else if (cur->right == NULL && cur->left != NULL) { //if cur has left
replacement = cur->left;
}
else if (cur->right != NULL && cur->left == NULL){ //if cur has right
replacement = cur->right;
}
else if (cur->right == NULL && cur->left == NULL){ //if cur has no child
replacement = NULL;
}
free(cur);
cur = replacement;
The function _removeLeftMost walks down the left child pointers until it sees the node to be replaced and then replaces it with the right child of that node. Something like:
Node *_removeLeftMost(node, remove) {
if (node == remove) {
return node->right; // Note that remove->left should be null
}
else {
node->left = _removeLeftMost(node->left,remove);
return node;
}
}
Also, the main call is something like
root = _removeNode(root, val);
So that handles your concern when the node is the root.

Changing From Assert Function in C To If Statement

I have found some code online for red black trees, and am trying to implement it.
I do not want to use the assert function though which the original code has located here
I am getting a seg fault on the line n->color = child->color; just before the delete fix. After debugging I discovered that the child did not exist in this case, and so the reason for the assert statement in the original code. I decided to add what I thought was appropriate with the additional if clause around everything from where child is dealt with downward.
However, now the program does not actually delete, because if the child does not exist, it never makes it into the loop. After trial and error I still cannot find where to close the if clause in order to take the place of the assert statement properly.
Please let me know your ideas!
Here is my "translated" code without the assert, and using an if statement instead.
void delete_node(int key)
{
node* child;
node* n ;
n = searchTree(key);
if(n == NULL)return;
if(n->left != NULL && n->right != NULL)
{
node* pred = n->left;
while(pred->right != NULL)
pred = pred->right;
n->value = pred->value;
n = pred;
}
if(n->right != NULL || n->left != NULL){
child = n->right == NULL ? n->left : n->right;
if(n->color == 'b')
{
n->color = child->color;
delete_fix1(n);
}
swap_nodes(n, child);
if(n->parent == NULL && child != NULL)
child->color = 'b';
free(n);
}
}
Test data (Seg Fault occurs when attempting to delete 4):
i stand for insert (insert occurs flawlessly as far as I can tell)
d stands for delete
i 7
i 8
i 1
d 8
i 4
i 10
d 4
i 11
This:
assert(n->left == NULL || n->right == NULL)
Is nowhere near this:
if (n->right != NULL || n->left != NULL)
Recheck your translation. The assert states that one of them must be NULL. your if-expr evals true if either are not NULL. Your if-expr passes if both are non-null, where the assert would fail. Likewise, your if-expr fails if both are NULL, while the assert would pass.
Don't take shortcuts when doing this kinda of thing. First. keep the asserts regardless of your added checks. Second, until it is up and working, copy the assert clauses verbatim in your if (expr): or (!(expr)) for bailout conditions.
verbatim check:
assert(n->left == NULL || n->right == NULL)
if (n->left == NULL || n->right == NULL)...
bailout check:
assert(n->left == NULL || n->right == NULL)
if (!(n->left == NULL || n->right == NULL))
bailout loud.
EDIT Translation of linked code with integrated if-expr
void rbtree_delete(rbtree t, void* key, compare_func compare)
{
node child;
node n = lookup_node(t, key, compare);
if (n == NULL) return; /* Key not found, do nothing */
if (n->left != NULL && n->right != NULL) {
/* Copy key/value from predecessor and then delete it instead */
node pred = maximum_node(n->left);
n->key = pred->key;
n->value = pred->value;
n = pred;
}
assert(n->left == NULL || n->right == NULL);
if (n->left == NULL || n->right == NULL) // << note: SAME as above
{
child = n->right == NULL ? n->left : n->right;
if (node_color(n) == BLACK) {
n->color = node_color(child);
delete_case1(t, n);
}
replace_node(t, n, child);
if (n->parent == NULL && child != NULL)
child->color = BLACK;
free(n);
}
verify_properties(t);
}

Resources