Faulty function that finds a node in a binary tree - c

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;
}

Related

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

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.

Find the first key bigger than X on Binary Search Tree

The successor of an element in a BST is the element's successor in the
sorted order determined by the inorder traversal. Finding the
successor when each node has a pointer to its parent node is presented
in CLRS's algorithm textbook (Introduction to Algorithms by MIT
press).
Is there a way to find the first value that is bigger than X without parent in the struct? Like:
typedef struct tree tree;
struct tree{
int value;
tree *left;
tree *right;
};
//Function:
tree *find_first_bigger(tree *t, int x){}
I tried working with:
tree *find_first_bigger(tree *t, int x){
if(t == NULL)
return NULL;
if((*t)->value > x)
find_first_bigger((*t)->left, x);
else if((*t)->value < x)
find_first_bigger((*t)->right), x);
else if((*t)->value == x){
if((*t)->right != NULL)
return tree_first_bigger((*t)->right);
else
return tree;
}
}
With this example(it's using letter but there its not a problem), if I try to search the first bigger than N(It should return me O) but it returns me N.
You have done 90% of the job.Allow me to do the remaining 10%.
Since t is a pointer to structure you should use t->left instead of (*t)->left and same applies while accessing right and value fields of the struct.
Now, Just modify your function as:
Add this as first line of your function
static tree* PTR=NULL;
Modify the second if condition as:
if(t->value > x)
{
PTR=t;
find_first_bigger(t->left, x);
}
Modify the second else if condition as:
else if(t->value == x)
{
if(t->right != NULL)
{
t=t->right;
while(t->left!=NULL)
t=t->left;
return t;
}
else return PTR;
}
Hence the correct function is
tree *find_first_bigger(tree *t, int x)
{
static tree* PTR=NULL;
if(t == NULL)
return NULL;
if(t->value > x)
{
PTR=t;
find_first_bigger(t->left, x);
}
else if(t->value < x)
find_first_bigger(t->right, x);
else if(t->value == x)
{
if(t->right != NULL)
{
t=t->right;
while(t->left!=NULL)
t=t->left;
return t;
}
else return PTR;
}
}
In the main function if pointer returned is NULL, this means that :the key itself is the largest key. Feel free for any queries.
I haven't tested this, but I think it should work. Let me know if it is wrong.
//c++ 11
#include<iostream>
using namespace std;
struct BSTNode{
int val;
BSTNode* left;
BSTNode* right;
};
int FindJustLarger(BSTNode*& node, int token, int sofarlarge){
// for invalid inputs it will return intial value of sofarlarge
// By invalid input I mean token > largest value in BST
if(node == nullptr)
return sofarlarge;
else if(node->val > token){
sofarlarge = node->val;
return FindJustLarger(node->left, token, sofarlarge);}
else
return FindJustLarger(node->right, token, sofarlarge);}
int main(){
BSTNode* head = new BSTNode{5, nullptr, nullptr};
FindJustLarger(head, 5, NULL);
delete head;
return 0;}
Some changes you can do in your code:
You have to return the values from the recursive calls
If the value is not found, return NULL. This means returning NULL if t->right == NULL on the last if.
When going to the left, if the value is not found there, the answer must be the node itself. In the case of N, it is the last node where we turn left: O. If it were P, the answer would be T itself.
After all those changes, the code should look like this:
tree *find_first_bigger(tree *t, int x){
if(t == NULL)
return NULL;
if(t->value > x) {
tree *answer = find_first_bigger(t->left, x);
if (answer != NULL)
return answer;
return t;
} else if(t->value < x) {
return find_first_bigger(t->right, x);
} else if(t->value == x) {
if (t->right != NULL)
return tree_first_bigger(t->right);
return NULL;
}
}
You can find the entire code I used to test in this gist.
In your question, you seemed to indicate that you want to find out InOrderSuccessor() of the the given value 'x'.
If 'x' does not necessarily exist in the tree, we need to change the algorithm. Given the example you provided and the problem statement, here is code for finding the next element in a BST.
The key cases are :
No greater element exists, because 'x' is the biggest.
'x' has a right child ?
YES: get left-most child of x's right sub-tree.
NO : return parent.
Key observation is that we don't update the parent pointer, whenever we go right in the tree.
tree *ptr = root;
tree *prnt = NULL;
while (ptr != NULL) {
if (x == ptr->key) {
if (ptr->right != NULL) {
return GetLeftMostChild(ptr->right);
} else {
return prnt;
}
} else if (x > ptr->key) {
ptr = ptr->right;
} else {
prnt = ptr;
ptr = ptr->left;
}
}
Here is the definition for leftMostChild()
tree *GetLeftMostChild(tree *n) {
tree *ptr = n;
while (ptr->left != NULL) {
ptr = ptr->left;
}
return ptr;
}

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 insertion not working

I've been playing about with this Binary search tree for a while but I can't seem to insert or change any of the tree properties.
My binary tree is defined as:
struct tree{
Node * root;
int size;
};
struct node{
int value;
Node * left;
Node * right;
};
Therefore my binary tree is composed of nodes. Now the bit that doesn't work:
void add(int value, Tree *t){
//1. if root is null create root
if(t->root == NULL){
t->root = nodeCreate(value);
t->size ++;
return;
}
Node * cursor = t->root;
while(cursor != NULL){
if(value == cursor->value){
printf("value already present in BST\n");
return;
}
if(value < cursor->value){
cursor = cursor->left;
}
if(value > cursor->value){
cursor = cursor->right;
}
}
//value not found in BST so create a new node.
cursor = nodeCreate(value);
t->size = t->size + 1;
}
Can someone tell me where I'm going wrong? I expected calls to add() would increase the size member as well as creating new nodes but I can't seem to get it.
I believe the changes below will fix your problem.
void add(int value, Tree *t){
if(t->root == NULL){
t->root = nodeCreate(value);
t->size ++;
return;
}
Node * cursor = t->root;
Node * last = null;
while(cursor != NULL){
last = cursor;
if(value == cursor->value){
printf("value already present in BST\n");
return;
}
if(value < cursor->value){
cursor = cursor->left;
}
if(value > cursor->value){
cursor = cursor->right;
}
}
//value not found in BST so create a new node.
cursor = nodeCreate(value);
if (value > cursor->value)
{
last->right = cursor;
}
else
{
last->left = cursor;
}
t->size = t->size + 1;
}
You're have both a design flaw and an outright-bug in your loop.
The design flaw: You're allocating a new node, but assigning to cursor doesn't mean you're assigning to the parent node left or right child pointer that got you there in the first place. You need a reference to the actual pointer you're going to populate. One way to do this is with a pointer-to-pointer, and as a bonus, this eliminates the is-my-root-null check at the beginning.
The outright bug: Your left-side movement clause (i.e. chasing a left-side pointer) will potentially change cursor to NULL. but the logic for chasing the right side is not excluded with an else if condition. If your search followed a left-side to null it would fault chasing the right side of a null pointer. This was obviously a problem.
void add(int value, Tree *t)
{
Node **pp = &(t->root);
while (*pp)
{
if(value == (*pp)->value) {
printf("value already present in BST\n");
return;
}
if(value < (*pp)->value)
pp = &(*pp)->left;
else if(value > (*pp)->value)
pp = &(*pp)->right;
}
*pp = nodeCreate(value);
t->size++;
}
I should also note that you can skip the equality check by assuming a strict-weak order. I.e. the following rule can be considered valid:
if (!(a < b) && !(b < a)) then a == b is true.
That makes your insertion simpler as well.
void add(int value, Tree *t)
{
Node **pp = &(t->root);
while (*pp)
{
if (value < (*pp)->value)
pp = &(*pp)->left;
else if ((*pp)->value < value)
pp = &(*pp)->right;
else { // must be equal.
printf("value already present in BST\n");
return;
}
}
*pp = nodeCreate(value);
t->size++;
}
You're not assigning any of your existing nodes to point to the new node. You walk through the tree, create a new node when you get to the end, but you don't set any existing nodes to point to the new node.
You might want to change your structure to something like:
if ( value < cusor->value )
{
if ( cursor->left )
{
cursor = cursor->left;
}
else
{
cursor->left = newNode(value);
break;
}
}
with similar logic for the right-hand cursor.

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.

Resources