warning: control reaches end of non-void function. C Binary Search Tree - c

I have an insert function for a Binary Search Tree and i can not find out why i am getting that error. Even if i put a return FALSE; right before the function ends it still happens. Any help is appreciated.
boolean insert(NODE **root, Employee e){
NODE *cursor,*temp;
// boolean status;
temp = (NODE *)malloc(sizeof(NODE));
assert(temp != NULL);
temp->element = (Employee *)malloc(sizeof(Employee));
assert(temp -> element != NULL);
*(temp -> element) = e;
temp -> left = NULL;
temp -> right = NULL;
if (*root == NULL) {
*root = temp;
return TRUE;
}
// tree is non-empty
cursor = *root;
while (cursor != NULL) {
if(e.ID < cursor -> element -> ID){
if(cursor -> left == NULL){
cursor -> left = temp;
return TRUE;
}
else cursor = cursor -> left;
}
//e goes to the right
else {
if (e.ID > cursor -> element -> ID){
if(cursor -> right == NULL){
cursor -> right = temp;
return TRUE;
}
else
cursor = cursor -> right;
}
else { // e is already in the tree
free(temp -> element);
free(temp);
return FALSE;
}
}
} // while cursor != NULL
} // insert

Even though a function actually does return something on all possible paths, the compiler can't necessarily determine that - to be able to do so in all cases would effectively prove the halting problem to be solvable. That's why this diagnostic is a warning, not an error.
Here's an example of a function that is easily seen to always return 0, but many compilers that try to warn you about unhandled return paths will issue the warning:
int foo( int x)
{
while (x >0) {
--x;
}
if (x == 0) return 0;
while (x < 0) {
++x;
}
if (x == 0) return 0;
}
However sometimes a simple analysis can determine that all control paths do return a value. The following will typically not generate a diagnostic:
int bar(int x)
{
if (x == 0)
return 0;
else
return 1;
}
In a function as complex as yours, it can be very difficult anyone (compiler or human) to determine that the while() loop never terminates except via a return inside it. You may want to add an assertion that always fails after the while if you expect that to be the case. Also you might consider changing the while (cursor != NULL) to for (;;) which 'documents' that this is a loop that will only end because of a return or break statement inside (and maybe have an assert(cursor != NULL) at the top).
Just for the record, putting a return FALSE; just before the end of your function does silence the warning.

Related

Iterative method to Recursive method C Language

I have tried to convert this method that is already working in my program to recursive way. Because I was asked to do it. The thing is I have tried see below but in my method when try to add to he position the method value this value is a great number and create segmentation.
This is my method in iterative way:
int researchList_getPosByCountry(tResearchList* list, tCountry *country) {
// Check preconditions
assert(list != NULL);
tResearchListNode *prev = NULL;
int pos;
// check if is an empty list
if (researchList_empty(list)) {
pos = -1;
}
else{
pos = 1;
prev = list->first;
while ((prev != NULL) && !country_equal(prev->e->country, country) ) {
prev = prev->next;
pos++;
}
}
if (prev == NULL) {
pos = -1;
}
return pos;
}
This is my method in recursive way:
assert(list != NULL);
tResearchListNode *prev;
int pos;
// check if is an empty list
if (researchList_empty(list)) {
pos = -1;
}
else{
pos = 1;
prev = list->first;
if ((prev != NULL) && !country_equal(prev->e->country, country) ) {
prev = prev->next;
pos = pos + researchList_getPosByCountry(list, country); //Debugging the segmentation is here
}
}
You will get an endless recursion, since you call researchList_getPosByCountry always starting from the begin of the list; again and again and ...
I suggest you introduce a second (then recursively used) function that calls itself with the respective next node and returns (a) the "greatest" negative number possible if the node was not found (thereby turning any intermediate results on the call stack into a negative one), or return 0 to denote "country found, take the count so far", or "1 + next try" to continue counting. The recursive part could look as follows; you need then to call this one from your int researchList_getPosByCountry(tResearchList* list, tCountry *country) and interpret a negative result accordingly:
int researchList_getPosByCountry(tResearchListNode* node, tCountry *country) {
if (!node) {
return INT_MIN;
} else if (countryEqual(...)) {
return 0;
} else {
return 1 + researchList_getPosByCountry(node->next,country);
}
}

Having trouble deciphering my teachers pseudo code

Im working on a Binary Search Tree assignment for class and for this function I need to follow my professor's pseudo code. Unfortunately, I'm not sure about one specific detail, and she refuses to clarify.
Link to the pseudo code is here:
https://imgur.com/a/rhjhEIa
SUBROUTINE insert(current, parent, node)
IF current is null
IF parent is null
root = node
ELSE
ID node.value < parent.value
parent.left = node
ELSE
parent.right = node
END IF
RETURN true
END IF
ELSE IF node.value = current.=value
RETURN false
ELSE IF ode.value < current.value
insert(current.left, current, node)
ELSE
insert(current.right, current, node)
END IF
END SUBROUTINE
In place of node, I've tried seemingly most of the allowed variables, including current, parent, (and even value, which didn't work. Shocker.)
bool recursiveInsert(Node* current, Node* parent, double value)
{
if (current == NULL)
{
if (parent == NULL)
{
}
else
{
if (current->value < parent->value)
{
parent->left = current;
}
else
{
parent->right = current;
}
return true;
}
}
else if(parent->value == current->value)
{
return false;
}
else if (parent->value < current->value)
{
insert(current->left, current->value, current);
}
else
{
insert(current->right, current->value, current);
}
}
I expect the output to add the value to the binary search tree and return true, but the program currently just throws a error whenever I get to the parts that require "node".
node in the context of the pseudocode is a previously allocated node containing the data being inserted into the tree. The initial caller allocates it (which is both pointless and never done in RW code).In reality, it is highly unlikely to actually do this pattern unless you're considering a library that potentially moves nodes out of one tree into another, and you want to avoid the expense of setting-up/tearing-down the nodes themselves.
Regarding the algorithm, it's fairly straightforward, though not very pretty:
If both current and parent are null, it means this must be the first node in the tree tracked by some global pointer root. Therefore, root is assigned the incoming node directly.
Otherwise, If current is null but parent is not if means parent is some potential leaf in the tree (meaning it has either a left, a right, or both contained pointers that are null), and you've landed on the null pointer. The insertion requires comparing against the parent value to know whether you hang the node on the left or the right. Note that this is inefficient, as you already did this comparison (it's how you got here in the first place).
Otherwise if current is not-null we simply check whether the values are equal, or less (greater is assumed if neither of those are true), and drive into the subtree of left or right if warranted. In that case, current.left or current.right become the recursed current, and current becomes the parent of said-same recursive call.
That's it. That's how that algorithm works. And frankly, it's marginal.
To implement this algorithm with your argument list (that takes a value rather than a node for the final argument), you need only ensure node allocation only happens when it is time to actually hang it, and only then (there are two such cases.
bool recursiveInsert(Node* current, Node* parent, double value)
{
bool result = false;
if (current == NULL)
{
if (parent == NULL)
{
root = malloc(sizeof *root);
root->value = value;
root->left = root->right = NULL;
}
else
{
Node *p = malloc(sizeof *p);
p->value = value;
p->left = p->right = NULL;
if (value < parent->value)
{
parent->left = p;
}
else
{
parent->right = p;
}
result = true;
}
}
else if (value < parent->value)
result = recursiveInsert(current->left, current, value);
else if (parent->value < value)
result = recursiveInsert(current->right, current, value);
return result;
}
When inserting a value into the tree, the call will look something like this:
recursiveInsert(root, NULL, value);
It's not pretty, but it works. That it relies on global root presence is probably the worst part of this algorithm. The multi-compare is probably second on the list of yuck.
A Different Approach
Ideally the root of the tree is passed in as an argument. Further, we can make the algorithm recursive as it is now, but no longer rely on some global root. Finally, we can reduce the argument count to two: the address of a pointer (initially the address of the root pointer), and the value being inserted. sing a pointer-to-pointer as the tree access method makes this algorithm elegant, whether using recursion or not. Both are provided below:
Recursive Insertion
bool treeInsert(Node **pp, double value)
{
bool result = false;
if (!*pp)
{
*pp = malloc(sizeof **pp);
(*pp)->value = value;
(*pp)->left = (*pp)->right = NULL;
result = true;
}
else if (value < (*pp)->value)
{
result = recursiveInsert(&(*pp)->left, value);
}
else if ((*pp)->value < value)
{
result = recursiveInsert(&(*pp)->right, value);
}
return result;
}
Iterative Insertion
bool treeInsert(Node **pp, double value)
{
bool result = false;
while (*pp)
{
if (value < (*pp)->value)
pp = &(*pp)->left;
else if ((*pp)->value < value)
pp = &(*pp)->right;
else break;
}
if (!*pp)
{
*pp = malloc(sizeof **pp);
(*pp)->value = value;
(*pp)->left = (*pp)->right = NULL;
result = true;
}
return result;
}
in either case, you invoke by passing the address of the root pointer (thus a pointer to pointer), where an empty try is signified by a NULL root:
treeInsert(&root, value);
Either function will accomplish the task at hand. I leave the error-hardening asa task for you (check your mallocs).
As you have mentioned, this is a function to insert a node in a binary search tree. The parameters are as follows
parent is the parent of the node being examined. This would be called with the root of the tree.
current is the left or right of the parent node being examined. While calling the function for the first time, you should use root->left if the value of the current node is less than root, or root->right if the value is greater than root. If root is null, then current should also be NULL
if (root == NULL)
{
ret = recursiveInsert(NULL, NULL, node);
}
else if (root->value < node->value)
{
ret = recursiveInsert(root->left, root, node);
}
else if (root-> value > node->value)
{
ret = recursiveInsert(root->right, root, node);
}
else
{
//same value, handle error
}
node is the new node to be added to the tree. The memory allocation for this node should be done before the call to recursiveinsert and the value should be specified.
Now let us look at the code that you have written.
The first mistake is to have the third parameter as a double. This should be a parameter of type node which should have already been allocated before.
From the condition check that
ELSE IF node.value = current.=value
RETURN false
it seems that node->value is of integer type.
Taking all this into consideration, the updated code is below.
Node* root = NULL; //global variable
...
bool recursiveInsert(Node* current, Node* parent, Node* node)
{
if (current == NULL)
{
if (parent == NULL)
{
root = node;
}
else
{
if (current->value < parent->value)
{
parent->left = node;
}
else
{
parent->right = node;
}
return true;
}
}
else if(node->value == current->value)
{
return false;
}
else if (parent->value < current->value)
{
recursiveInsert(current->left, current, node);
}
else
{
recursiveInsert(current->right, current, node);
}
}

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.

Resources