For a binary search tree structure in C that cannot be changed:
struct bstnode {
int item;
struct bstnode* left;
struct bstnode* right;
};
struct bst {
struct bstnode* root;
};
How can we find the sum of values that are greater than a number(num)?
(we cannot travel the whole tree or convert this bst to an array).
the function declaration is:
int sum_greater(struct bst * t, int num)
Basically, my method is to use recursion:
when num equals item in the current node, we sum the right part of this tree.
when num greater than item in the current node and node->right is greater than num, we sum the right part of this tree.
But I dont know how to deal with the situation when current node is less than num.
You're making this a bit too complicated. Your base case is hitting a leaf node (which you already know how to handle). You have three recursion cases:
current > num
result = current +
recur on right child +
recur on left child
current = num
result = current +
recur on right child
current < num
result = recur on right child
return result
All you can do is to prune off the left subtrees that are too small as you find them. don't waste effort looking ahead: the recursion will handle that just fine.
Note that you cannot stop early dependent on the right child's value: that child may well have right-descendants with arbitrarily large values.
So the user #Prune has already pointed out the idea which consists of getting ride of sub trees that are less than the desired value.
int sum_greater(struct bst * t, int num){
struct bstnode *ptr = t->root;
if(!ptr)
return 0;
struct bst right_tree = { t->root->right };
struct bst left_tree = { t->root->left };
if(ptr->item > num)
return ptr->item + \
sum_greater(&left_tree, num) + \
sum_greater(&right_tree, num);
else // ptr->item =< num
return sum_greater(&right_tree, num);
}
For a complete example, run the code from : Full sum_greater code
how to deal with the situation when current node is less than num.
Only add the right BST in that case, when current node is less than or equal to num. Else add both left, right and the ->item.
int BST_sum_gt(const struct bstnode* node, int num) {
if (node == NULL) {
return 0;
}
if (node->item > num) {
return BST_sum_gt(node->left) + node->item + BST_sum_gt(node->left);
}
return BST_sum_gt(node->left);
}
int sum_greater(const struct bst * t, int num) {
return BST_sum_gt(t->root);
}
Or a less recursive approach
int BST_sum_gt(const struct bstnode* node, int num) {
int sum = 0;
while (node) {
if (node->item > num) {
sum += BST_sum_gt(node->left) + node->item;
}
node = node->right;
}
return sum;
}
Related
I need to find the sum of the values of its deepest leaves. This code works but not correctly.
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
int sum = 0;
void dfs(struct TreeNode *root, int lvl){
if(root == NULL) return ;
int maxlvl = -1;
if(lvl > maxlvl){
maxlvl = lvl;
sum = root->val;
}
else if (lvl == maxlvl){
sum += root->val;
}
dfs(root->left, lvl+1);
dfs(root->right, lvl+1);
}
int deepestLeavesSum(struct TreeNode* root){
dfs(root,0);
return sum;
}
I suspect that the error is that I do not transfer the sum and declare it globally. But I don't really understand how to pass it to me and what I should put in the function.
There are a few issues with this code. First of all, maxlvl is always either -1 or the current level, so the else if never gets reached and instead sum is made equal to the last node that was visited. I assume that maxlvl is the deepest you want to search in the tree, so I would make it a global variable with a constant value.
Furthermore, you are supposed to sum the deepest leaves, yet there is no check to see if you have actually reached a leaf.
I will assume you also have to sum the values in nodes at the deepest search layer, and suggest this edit:
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
int sum = 0;
int maxlvl = 10;
void dfs(struct TreeNode *root, int lvl){
if(root == NULL) return;
if (lvl == maxlvl || !(root->left || root->right)){
sum += root->val;
return;
}
dfs(root->left, lvl+1);
dfs(root->right, lvl+1);
}
int deepestLeavesSum(struct TreeNode* root){
dfs(root,0);
return sum;
}
In one of the C exercises I had to create a function for binary tree traversal with a given depth.
My first thought was to use a for loop (traverse_preorder_bad). Finally, I could complete the task with a variable initialization + if (traverse_preorder_working), but I am still struggling to understand why the for solution didn't work.
Could someone explain me the difference? Is there an elegant solution?
Code on Ideone
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const int RANGE = 1000;
typedef struct node_t
{
int data;
struct node_t *left;
struct node_t *right;
} node_t;
node_t *node_new(int data);
node_t *node_insert(node_t *tree, int data);
void traverse_preorder_working(node_t *tree, int depth);
void traverse_preorder_bad(node_t *tree, int depth);
int main(int argc, char *argv[])
{
node_t *tree = NULL;
// Random seed
srand((unsigned) time(NULL));
// Create the root node
tree = node_new(rand() % RANGE);
node_insert(tree, 5);
node_insert(tree, 1);
printf("Expected output:\n");
traverse_preorder_working(tree, 10);
printf("Bad output:\n");
traverse_preorder_bad(tree, 10);
return 0;
}
node_t *node_new(int data)
{
node_t *tree;
tree = malloc(sizeof(*tree));
tree->left = NULL;
tree->right = NULL;
tree->data = data;
return tree;
}
node_t *node_insert(node_t *tree, int data)
{
if (!tree)
return node_new(data);
if (data == tree->data)
return tree;
if (data < tree->data)
tree->left = node_insert(tree->left, data);
else
tree->right = node_insert(tree->right, data);
return tree;
}
void traverse_preorder_working(node_t *tree, int depth)
{
int i;
if (!tree)
return;
printf("%d\n", tree->data);
i = 1;
if (tree->left && i <= depth)
{
traverse_preorder_working(tree->left, depth - i);
i++;
}
i = 1;
if (tree->right && i <= depth)
{
traverse_preorder_working(tree->right, depth - i);
i++;
}
}
void traverse_preorder_bad(node_t *tree, int depth)
{
if (!tree)
return;
printf("%d\n", tree->data);
for (int i = 1; tree->left && i <= depth; i++)
traverse_preorder_bad(tree->left, depth - i);
for (int i = 1; tree->right && i <= depth; i++)
traverse_preorder_bad(tree->right, depth - i);
}
The problem is that traverse_preorder_working is correctly recursive, when visiting a node you call traverse_preorder_working recursively on the left subtree (and then right)
Instead traverse_preorder_bad is still recursive but it makes no sense, when you visit a node you then call traverse_preorder_bad n-times on the same subtree with a different depth.
If you check invocation tree for something like:
a
/ \
b c
/ \ / \
d e f g
You can see that traverse_preorder_working(a,5) goes traverse_preorder_working(b,4), traverse_preorder_working(d,3) .. while other function goes
traverse_preorder_bad(a,5),
traverse_preorder_bad(b,4), visit subtree
traverse_preorder_bad(b,3), visit subtree
traverse_preorder_bad(b,2), visit subtree
traverse_preorder_bad(b,1), visit subtree ...
from the same level of recursion, which means that each node will be visited multiple times with different depth limits; this doesn't happen in the first correct version.
If each invocation of traverse_preorder_bad should visit a node and start visiting both subtrees but inside the code you call visit recursively more than twice (which is the case, since you have a loop) then something is wrong.
The "for" version make no sense. You only want to print the tree for a given node once, so you should only call traverse on each node once.
Additionally, based on one of your comments in your post, I think you have some misunderstandings about your working function.
You have multiple checks for whether the tree is null (both as the current tree or as its children)
i ever only has a value of one while it is being used. You could simplify to
void traverse_preorder_working(node_t *tree, int depth){
if(!tree || depth <= 0){
return;
}
printf("%d\n", tree->data);
traverse_preorder_working(tree->left, depth - 1);
traverse_preorder_working(tree->right, depth - 1);
}
All of the checks to see if we not should explore a node - either because it doesn't exist or it is too deep - are done only once (at the start of the function), and not repeated twice for each child. No i variable that does nothing.
The elegant solution here (without recursion) is Morris Traversal. The idea is to add indirection edge from the left subtree's rightmost node to the current node.
The full explanation of the algorithm is here: http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/
Of course you can modify this algorithm not to go deeper then you current depth.
I'm currently implementing a Binary Search Tree and I'm trying to find the smallest value in the tree with a function like this:
int smallest(Tr *T, void *Item) {
TNode * n;
if(Size(T) == 0)
return 0;
while(n->left != NULL) {
n = n->left;
}
return 1;
}
Where I have the structs:
typedef struct TNodeTag {
void *v;
struct TNodeTag*left, *right, *parent;
} TNode;
typedef struct {
TNode *root;
TNode *current;
void * (*copyItems) (void *, void *);
int value;
} Tr;
And at first a initialize function:
void Initialize (Tr *T,void * (*copyItems) (void *, void *),{
T->root = NULL;
T->copyItems = copyItems;
T->value = 0;
}
Where void * Item is the address of where a copy of the smallest node should be stored (using the copyValue function)(Which I'm not sure how to create) . Tr * T is a pointer to the first struct. The function smallest, is so posed to return 1 if it can find a smallest value, 0 otherwise (tree is empty).
I'm not sure if my implementation of finding the smallest node is correct, since my function will always return 1,unless the tree is empty?
If I understand correctly, the function "smallest" must return 1 if there exists a smallest value in the tree and 0 otherwise. That doesn't sound very useful, since there will always be a smallest value in the tree, so long as the tree is not empty. In this regard, your function is correct.
However, your function tries to de-reference the pointer n before it is being assigned to anything, in the while loop. All bets are off as to what will actually happen and this is probably not something you want. (I imagine the compiler is optimizing this away since n is never used.) I think what you're trying to do is find the smallest value, in which case, you should first assign the address of root node of the tree to n. You could do
...
n = T->root;
while(n->left != NULL) {
n = n->left;
}
so that, after the loop, n will point to the node with the smallest value.
Hope this helps :)
I was working on the exercises here :
"http://cslibrary.stanford.edu/110/BinaryTrees.html#s2"
I wrote a function that decides if a Tree is a BST(return 1) or not(return 0) but I'm not sure if my code is totally good, I tested it for a BST and a non-BST Tree and it seems to work correctly. I want to know the opinion of the community :
Updated Code :
consider the Tree ( not a BST ) :
5
/ \
2 7
/ \
1 6
my Idea is to compare 2 with 5 if it's good, then 1 with 5, and if it's good then 6 with 5 if it's good then 1 with 2 if it's good then 6 with 2 if it's good then 5 with 7 ; if it's good isBST() returns 1. this code is supposed to do it recursively.
the node structure :
struct node {
int data;
struct node* left;
struct node* right;
};
the code :
int lisgood(struct node* n1,struct node* n2)
{
if(n2 == NULL)
return 1;
else{
int r = lisgood(n1,n2->left)*lisgood(n1,n2->right);
if(r){
if(n1->data >= n2->data)
{
return r;
}
else return 0;
}
else return r;
}
}
int risgood(struct node* n1,struct node* n2)
{
if(n2 == NULL)
return 1;
else{
int r = risgood(n1,n2->right)*risgood(n1,n2->left);
if(r){
if(n1->data < n2->data)
{
return r;
}
else return 0;
}
else return r;
}
}
int isBST(struct node* node)
{
if(node == NULL)
return 1;
else{
if(lisgood(node,node->left)&&risgood(node,node->right)){
return (isBST(node->left)&&isBST(node->right));
}
else return 0;
}
}
Your code doesn't really work - not even for the example you showed. You never compare 5 to 6. Basically you are comparing the root of a sub-tree with root->left, root->left->left, root->left->left->left, etc. Then you are comparing root with root->right, root->right->right, etc., but you never compare root with the other nodes in the subtree. The problem is that you don't compare a tree's root with every element on its right and left subtrees, and you should.
This is a known interview question. The simpler way to solve it is to pass in the minimum and maximum values allowed for a sub-tree as parameters.
Here's how it works with the example tree you showed: you see 5, thus, the maximum value for any node on 5's left subtree is 5. Similarly, the minimum value for any node on 5's right subtree is 5. This property is applied recursively to check that every node's value is consistent with the requirements. Here's a working implementation (assumes a tree with no duplicates):
#include <stdio.h>
#include <limits.h>
struct tree_node {
int key;
struct tree_node *left;
struct tree_node *right;
};
static int is_bst_aux(struct tree_node *root, int min, int max) {
if (root == NULL) {
return 1;
}
if (!(min < root->key && root->key < max)) {
return 0;
}
if (!is_bst_aux(root->left, min, root->key)) {
return 0;
}
return is_bst_aux(root->right, root->key, max);
}
int is_bst(struct tree_node *root) {
return is_bst_aux(root, INT_MIN, INT_MAX);
}
I am working with a ternary search tree. Following code should give you an overview of how the tree looks like. Every leaf will contain a pointer to a linked list which contains pointer to the head node. Every leaf can have at most 3 nodes. Therefore after the root leaf has been filled with 3 data values the next value if it is smaller than the first node will get inserted in to the left if it is greater it gets inserted in to the right and if it is in the middle it will get inserted in to the centre child.
struct data
{
int val;
};
struct node
{
struct node* next;
struct data* dta;
};
struct linkedList
{
int size;
struct node *head;
};
struct leaf
{
struct linkedList* ll;
struct leaf* left;
struct leaf* right;
struct leaf* center;
struct leaf* parent;
};
struct tree
{
struct leaf* root;
};
I am currently trying to create a function that takes in a tree and a int value as inputs. Then it checks every leaf in the tree to see if some leaf equals the int value and if it does it will return 1 and 0 otherwise.
Following is my code
int totalLeaf(struct leaf *lf)
{
int sum = 0;
struct node *temp = lf->ll->head;
while(temp!=NULL)
{
sum = sum + temp->dta->val;
temp = temp->next;
}
printf("sum is : %d\n",sum);
return sum;
}
int searchTotal(struct tree *tr,int total)
{
if(tr->root == NULL)
{
return 0;
}
else
{
return searchTotal_r(tr->root,total);
}
}
int searchTotal_r(struct leaf *lf,int total)
{
if(lf==NULL)
{
return 0;
}
if(totalLeaf(lf) == total)
{
return 1;
}
else
{
searchTotal_r(lf->left,total);
searchTotal_r(lf->center,total);
searchTotal_r(lf->right,total);
}
return 0;
}
Can anyone suggest where i have gone wrong and how i can fix this issue?
else
{
searchTotal_r(lf->left,total);
searchTotal_r(lf->center,total);
searchTotal_r(lf->right,total);
}
Change to:
else
{
return searchTotal_r(lf->left,total) ||
searchTotal_r(lf->center,total) ||
searchTotal_r(lf->right,total);
}
The way you currently have it, the recursive searches don't actually matter because you always return 0 even if you find something.