Find max and min value of BST - c

Hello stackoverflowers,
i am facing a problem with my function in C, i want to create a function that give me the min and max value in BST.
The problem is when i use this function it returns the same value for min and max:
void Find_Min_Max(node *bt,int* maxint,int* minint)
{
node *tmp = bt;
if( bt == NULL)
{
*maxint = 0; // Only if the tree contains nothing at all
*minint = 0; // Only if the tree contains nothing at all
}
if( bt->left)
return Find_Min_Max(bt->left,&(*maxint),&(*minint));
*minint = bt->data;
if( tmp->right)
return Find_Min_Max(tmp->right,&(*maxint),&(*minint));
*maxint = tmp->data;
}
But when i use it to give me just one result max/min, i delete this part of code, everything work perfectly:
if( tmp->right)
return Find_Min_Max(tmp->right,&(*maxint),&(*minint));
*maxint = tmp->data;
Any idea how this will work?.
Thank you in advance.

It's not really easy / intuitive to recursively compute max and min at the same time in the same function. I would even say it's not possible, because those are two completely different traversals.
You should have a function to get the minimum, a function to get the maximum, and call each of them inside Find_Min_Max.
This would be a possible approach:
int find_min(node *n) {
if (n == NULL) {
return 0;
}
while (n->left != NULL) {
n = n->left;
}
return n->data;
}
find_max is similar, but traverses right links only:
int find_max(node *n) {
if (n == NULL) {
return 0;
}
while (n->right != NULL) {
n = n->right;
}
return n->data;
}
Then, find_min_max() is easy to code:
void find_min_max(node *bt, int *min, int *right) {
*min = find_min(bt);
*max = find_max(bt);
}
find_min() and find_max() could be recursive, but the iterative approach has the desirable property of using constant memory (and consequently avoids stack overflows).

To find the minimum value in a BST, you follow the chain of left children from the root until you reach a node with no left child. That node contains the minimum value (even if it does have a right child).
The algorithm to find the maximum is exactly the mirror image: follow the chain of right children until you reach a node with no right child. That node contains the maximum value.
It does not make sense to try to perform both traversals at the same time, because they follow completely different paths. If you want a single function to discover both the minimum and the maximum value, then it doesn't make much sense for that function itself to be recursive. It could, however, wrap calls to two separate recursive functions, one to find the minimum, and the other to find the maximum.

Finding min and max value in a BST are very easy. Please check both code snippet below I explain how these codes work.
public int minValueInBST(Node node){
if (node == null) throw new IllegalStateException();
Node current = node;
while (current.leftChild != null) {
current = node.leftChild;
}
return current.value;
}
To find the minimum value in BST we have to find the leftmost leaf node because that node contains the minimum value. So at first, we check the root node is null or not if null we throw IllegalStateException otherwise we find the left node, at last, we return the left node value.
public int maxValueInBST(Node node){
if (node == null) throw new IllegalStateException();
Node current = node;
while (current.rightChild != null) {
current = node.rightChild;
}
return current.value;
}
To find the maximum value in BST we have to find the rightmost leaf node because that node contains the maximum value. So at first, we check the root node is null or not if null we throw IllegalStateException otherwise we find the right node, at last, we return the right node value.

// try this
tree_node *min(tree_node *root)
{
if (!root)
{
printf("Tree is empty");
exit(1);
}
tree_node *ret_val;
if (root->left == NULL)
{
ret_val = root;
}
else
{
ret_val = min(root->left);
}
return ret_val;
}
tree_node *max(tree_node *root)
{
if (!root)
{
printf("Tree is empty");
exit(1);
}
tree_node *ret_val;
if (root->right == NULL)
{
ret_val = root;
}
else
{
ret_val = max(root->right);
}
return ret_val;
}
complete code

Related

How do I find the Nth element in a binary search tree?

I have a binary search tree in C, the goal currently is to find the Nth element in the tree. I am attempting to do this recursively, however this is not paramount. I have access to the amount of nodes under any given node (inclusive).
I tried this block of code:
TreeNode* findNthElement(int N, TreeNode* tree) {
static int count = 0;
printf("nodeCount: %d\nN: %d\nCount: %d\n", tree->nodeCount, N, count);//debug
//null case
if (tree == NULL) {
return NULL;
}
//recursion
if (count <= N) {
findNthElement(N, tree->left);
count++;
if (count == N) {
count = 0;
return tree;
}
findNthElement(N, tree->right);
}
}
This is supposed to be a recursive function to complete my task but count's value is always 0 even though it is static. I have also tried initializing count outside of the function and resetting it to 0 upon success or failure but that has also not succeeded.
Your code ignores the node that is returned from the recursive call, so if that recursive call had found the target node, the caller is not aware of it. Moreover, after the findNthElement(N, tree->right) call, nothing is returned.
Also, you shouldn't use a static count. The counting logic can be satisfied by reducing the value that will be passed as N-argument to the recursive call.
Here is an implementation:
TreeNode* findNthElement(int n, TreeNode* tree) {
if (tree == NULL) {
return NULL;
}
int currentNum = tree->left == NULL ? 1 : tree->left->nodeCount + 1;
return n == currentNum ? tree // Found it!
: n < currentNum ? findNthElement(n, tree->left)
: findNthElement(n - currentNum, tree->right);
}
this code is beyond my knowledge, but maybe count++ needs to go before recursing? Because you are calling the recursion without increasing the count in your code.
Example:
if (count <= N) {
count++;
findNthElement(N, tree->left);
You dont have to define count as static at all, you can directly increment parameter and call recursively until N == count.
Whenever you call the function, even recursively, then a new count variable will be created in the memory stack.
TreeNode* findNthElement(int N, TreeNode* tree, int count) {
TreeNode * nthTree = NULL;
if(tree == NULL)
return NULL;
//Found the Nth element
if (count == N){
return tree;
}
//Not using ++count just for clarity
//First it will check left subtree, if its Nth then return it else go right
nthTree = findNthElement(N, tree->left, count+1); //Recursive call for left node
//Recursive call for right node
return (nthTree == NULL) ? findNthElement(N, tree->right, count+1) : nthTree;
}
in order to find the nth smallest element in BST, you can apply logic as follows:
using System.Collections.Generic;
public int smallElement(int k)
{
Node<T> node = Root;
int count = k;
int sizeOfSubTree =0;
while (node != null)
{
sizeOfSubTree = node.SizeOfLeftSubTree();
if(sizeOfSubTree +1 == count)
{
return node.Value;
}
else if(sizeOfSubTree +1 < count)
{
node=node.Right;
count -= sizeOfSubTree +1 ;
}
else
{
node = node.Right;
}
}
return -1;
}
you can also check following resources to get help:
in-order traversal to find nth node
Find k’th smallest node in a Binary Search Tree (BST)
hope this might help you.

How to find the depth of a specific node in a BST in c

I am trying to find the depth of a specific node noted by a pointer in c, but I cant seem to get it right
int depth(Node *root, Node *N){
// Need to find the root N
// At the same time count how many depths you can go down
// If the root is NULL, then no tree and return -1
if (root == NULL){
return -1;
}
// If the root node equals the node N, then return 0
if (root->data == N->data){
return 0;
}
// Search the tree and add one each time recursion called
int count = -1;
if (N->data < root->data){
root->left->data = depth(root->left, N);
count++;
}
else if (N->data > root->data){
root->right->data = depth(root->right, N);
count++;
}
else{
}
return count;
}
Any help in solving this would be appreciated.
The pseudo code for such a function is along the lines of this, assuming root = level 0:
int search (const node_t* node, int level)
{
if(node == NULL)
return -1;
if(node->data == key)
return level;
const node_t* node next;
if(node->data < key)
next = node->right;
else if(node->data > key)
next = node->left
return search (next, level+1);
}
First called as search(root, 0);
Though as usual, recursion in C is almost certainly the wrong solution to any problem. The above can rather trivially be rewritten as sane, readable, fast loops instead.

Convert binary tree into simple linked list

struct Monitor {
int codMonitor;
char* producator;
float diagonala;
int numarPorturi;
};
struct nodls {
Monitor info;
nodls* next;
};
nodls* creareNod(Monitor m) { --create node
nodls* nou = (nodls*)malloc(sizeof(nodls));
nou->info.codMonitor = m.codMonitor;
nou->info.producator = (char*)malloc(sizeof(char)*(strlen(m.producator) + 1));
strcpy(nou->info.producator, m.producator);
nou->info.diagonala = m.diagonala;
nou->info.numarPorturi = m.numarPorturi;
nou->next = nou;
return nou;
}
nodls* inserare(nodls* cap, Monitor m) { -- insert
nodls* nou = creareNod(m);
if (cap == NULL) {
cap = nou;
cap->next = cap;
}
else
{
nodls* temp = cap;
while (temp->next != cap)
temp = temp->next;
temp->next = nou;
nou->next = cap;
}
return cap;
}
void afisareMonitor(Monitor m) { -- display struct
printf("\nMonitorul cu codul %d, producatorul %s, diagonala %f, numarul de porturi %d",
m.codMonitor, m.producator, m.diagonala, m.numarPorturi);
}
void traversare(nodls** cap) { --display function
nodls* temp = *cap;
if (cap == NULL)
printf("\nLista este goala");
while (temp->next != *cap) {
afisareMonitor(temp->info);
temp = temp->next;
}
afisareMonitor(temp->info);
}
void stergereNod(nodls* cap) --delete node function
{
.......
}
void dezalocare(nodls* cap) { free allocate space
............
}
How I can convert using the following code, my binary tree into a simple linked list. This can be done with recursion maybe.
getLeavesList(root) {
if root is NULL: return
if root is leaf_node: add_to_leaves_list(root)
getLeavesList(root -> left)
getLeavesList(root -> right)
}
So, if the root is NULL, this is, if the function received no valid pointer, then return an error message.
If the root is a leaf, this is, if both left and right child nodes are NULL, the you have to add it to the list of leaf nodes.
Then you recursively call the function with the left and right child nodes.
https://www.geeksforgeeks.org/tree-traversals-inorder-preorder-and-postorder/
This article covers 3 simple depth-first approaches(preorder, inorder, postorder) to traverse a binary tree. It also has a nice compact example in C.
The pseudo-code algorithm you provided is actually the proper preorder approach.
The only modification you have to make in the
void printPreorder(struct node* node)
method is to replace the printing of the node's data:
printf("%d ", node->data);
with checking if the node is a leaf and if yes adding it to a list:
if((node->left == NULL) && (node->right == NULL))
{
appendList(&node);
}
Of course appendList is just my ad-hoc creation but based on the code that you've provided in the question you'll know how to add to a linked-list. If not please feel free to ask.
ps: https://www.geeksforgeeks.org/ is an amazing resource hats of to those guys for the amazing work!
psps: If you'd like to return an error message when the function is called with NULL for the first time, that is if no valid tree is passed to the traversal, I'd suggest you to make a wrapper function that will call the recursive one. Then, in that wrapper you can check if the head passed to it is NULL before you even call the recursive method at all.

Binary Tree Insert without ordering

Is there any way to insert a new node in a binary tree (not bst) without comparing key values? The following code only works for the very first three nodes.
node *insert (node *root, int *key) {
if (root==NULL) {
root=newNode(root, key);
return root;
}
else if (root->left == NULL)
root->left=insert(root->left,key);
else if (root-> right == NULL)
root->right=insert(root->right,key);
return root;
}
If you change
else if (root-> right == NULL)
to just
else
Then it would have the effect of always adding to the right.
If you want it to randomly pick, add a call to srand outside this function.
srand(time(NULL));
Then in this function, call
else if (rand() > MAX_RAND / 2) {
root->right = insert(root->right, key);
} else {
root->left = insert(root->left, key);
}
at the end of your existing if/else structure.
See also:
Lack of randomness in C rand()
If your tree tracks its height at each node, you could add after your null checks something like
else if (root->left->height <= root->right->height) {
root->left = insert(root->left, key);
} else {
root->right = insert(root->right, key);
}
That would keep the tree balanced automatically. But it requires additional code to manage the height. E.g.
root->height = 1 + ((root->left->height > root->right->height) ? root->left->height : root->right->height);
I leave it up to you whether that additional overhead is worth it.
The people suggesting using a heap are suggesting using the indexes as the ordering. This is kind of useless as a heap, but it would make a balanced binary tree. So the root node would be the first inserted and the most recent inserted would be the rightmost leaf.
You could just keep track of the height of each node, and always insert it into the side with fewer children:
node *insert (node *root, int *key) {
if (root==NULL) {
root=newNode(root, key);
root->height = 0
}
else if (root->left == NULL) {
insert(root->left,key);
}
else if (root->right == NULL) {
insert(root->right,key);
}
else if (root->left->height <= root->right->height) {
insert(root->left,key);
} else {
insert(root->right,key);
}
root->height++
}
Comparing values is actually irrelevant, the only think you need to do is set a pointer. Since you didn't specify any real requirements, one solution could be as follows:
Changing the signature a bit so now you have a pointer to an already allocated node:
void insertNode(node *&root, node *newNode) {
if (root == NULL) {
root = newNode;
return;
}
if (root->left == NULL) {
root-left = newNode;
return;
}
helperInsert(root->left, newNode);
return;
}
This will set the head (assuming I got the signature right), and otherwise check the left child.
void helperInsert(node *it, node *newNode) {
if (it->left == NULL) {
it->left = newNode;
return;
}
helperInsert(it->left, newNode);
return;
}
This is obviously a flawed approach (the tree will not be balanced at the slightest), almost treating the tree as a linked list, but to my best understanding of the question, this is an example of how it can be done.
In
else if (root->left == NULL)
root->left=insert(root->left,key);
you know root->left is NULL so why to do the recursive call ?
Of course same for the next else
The following code only works for the very first three nodes.
If both left and right are non NULL you do not insert, that time it was necessary to do the recursive call on one of the two branches, and you will consider the key (so insert ordered) to decide which one. Note that the 2 tests to NULL you did are not correct if you insert to have a sorted tree ...
The heap advice is most sound. You don't need to heapify anything, just follow the rules that an element at index k has children at 2*k + 1 and 2*k + 2.
Another approach, useful when there is no array, but the nodes are generated on the fly, is to fill the tree level-wise. Notice that at level k there are 2 ** k slots, conveniently indexed by a k-bit integer. Interpret the index as a path down the tree (clear bit tells to follow left child, set bit tells to follow a right one), along the lines of:
void insert_node(struct node * root, struct node * node, unsigned mask, unsigned path)
{
while ((mask >> 1) != 1) {
root = mask & path? root->right: root->left;
}
if (mask & path) {
assert (root->right == NULL);
root->right = node;
} else {
assert (root->left == NULL);
root->left = node;
}
}
void fill_level_k(struct node * root, unsigned k)
{
unsigned slots = 1 << k;
for (unsigned slot = 0; slot < slots; slot++) {
struct node * node = generate_new_node();
insert_node(root, node, slots, slot);
}
}

return current node from BST

Hello I've run into an issues I cannot seem to resolve. I have a BST that I am traversing through and checking ranks. I have a method checkRank(link head, targRank) that takes in the head node and traverses through the tree until it finds a node with an equal rank to targRank. What I am trying to do is have the checkRank function return the current node it found the equal rank at. What would be the best way to achieve this because all my attempts seem to return the current node as the head?
typedef struct node* link;
struct node
{
Item item; // Data for this node
link l, r; // left & right links
int rank;
};
Func call:
link head;
checkRank(head, 13);
Func:
link checkRank(link h,int targetRank)
{
if (h != NULL)
{
if (h->rank < targRank)
{
checkRank(h->r, targRank);
}
if (h->rank > tarRank)
{
checkRank(h->l, targtRank);
}
if (h->rank == targRank)
{
return ??;
}
}
else
{
printf("Equiv rank could not be found\n");
}
}
First of all, you need to return something along each path. Have you considered something like the following:
link check_rank(link h, int target) {
if (h == NULL) {
printf("equivalent rank could not be found\n");
return NULL;
}
if (h->rank < target)
return check_rank(h->r, target);
if (h->rank > target)
return check_rank(h->l, target);
return h;
}
Functions have to always return a value and many recursive functions will follow the pattern of (1) return a sentinel to stop recursion when the appropriate condition is met or (2) recurse and return whatever the recursive call returns.

Resources