Problem with binary tree & depth first search - c

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

Related

searching an element in binary tree using in order traversal

struct tnode
{
int val;
struct tnode *left;
struct tnode *right;
};
int search(struct tnode *root, int val)
{
int p = 0;
int q = 0;
if (!root) return 0;
p = search(root->left, val);
if (p == 1) return 1;
if (root->val == val) return 1;
q = search(root->right, val);
if (q == 1) return 1;
}
I am not understanding how the above code is returning 0 when val is not found while searching the tree.
What you have there is an unstructured function. There are four return statements and five possible return paths. One of the returns explicitly returns zero, the others explicitly return 1, therefore either you are calling search with NULL for root or the fifth implicit return path just happens to return zero.
Dial up the warning level on your compiler, it should have flagged the fact that not all execution paths return a value.
I suggest you rearrange your logic such that there is a single return statement at the end of the function.
Here, I am using stack for the iterative inorder traversal of a tree.
int find_element(struct node *root,int val){
if(!root) return 0;
std::stack<node*> s;
while(!s.empty() || root){
if(root){
s.push(root);
root=root->left;
}
else
{
root=s.top();
s.pop();
if(root->val==val) return 1;
root=root->right;
}
}
return 0;
}

sum of nodes greater than a number in BST

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

Search function for a tree

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.

How to get entire contents of binary tree in array form?

I have a C structure that represents a binary tree:
struct btree {
char *word;
int frequency;
struct btree *left;
struct btree *right;
};
I want to create a function btree_list(struct btree*) that returns an array of all the btree objects in the binary tree passed to it. Order does not matter.
Here is an example of how this function would work:
struct btree *T = populate_with_random_values();
struct btree *entries = (struct btree*) malloc(sizeof(struct btree) * btree_size(T));
entries = btree_list(T);
while (*entries != NULL) {
printf("There are %d occurences of the word %s", entries->frequency, entries->word);
entries++;
}
Also for each element E in entries, E->left and E->right should be set to NULL since they aren't technically being used. How would I go about implementing this?
This could be the array:
typedef struct {
struct btree **data;
size_t count;
} t_tbl;
t_tbl *tbl_create(size_t count)
{
t_tbl *new = NULL;
if (count > 0) {
new = malloc(sizeof(t_tbl));
new->data = malloc(count * sizeof(struct btree *));
new->count = 0;
}
return new;
}
void tbl_destroy(t_tbl *table)
{
if (table) {
free(table->data);
free(table);
}
}
And this could be the process:
void btree_populate_array(const t_node *root, t_tbl *table)
{
if (root->left) btree_populate_array(root->left, table);
table->data[table->count++] = root;
if (root->right) btree_populate_array(root->right, table);
}
if (root) {
t_tbl *table = tbl_create(btree_size);
btree_populate_array(root, table);
/* Do stuff with array */
tbl_destroy(table);
}
You have to check malloc, if you don't know the size of btree:
void btree_count(const t_node *root, size_t *count)
{
if (root->left) btree_count(root->left, count);
(*count)++;
if (root->right) btree_count(root->right, count);
}
size_t btree_size = 0;
if (root) {
btree_count(root, &btree_size);
}
Rather than returning the array just pass its base address to make your life easier and return the count of your array:
int TraverseTree(int arr[],btreenode *root, int depth)
{
static int count = 0;
if (root)
{
count++;
TraverseTree(arr,root->right,depth+1);
arr[depth]=root->data;
TraverseTree(arr,root->left, depth+1);
}
return count;
}
Well, do you want a preorder, inorder, or postorder traversal?
Here's a preorder example in pseudocode: (credit to Wikipedia)
iterativePreorder(node)
parentStack = empty stack
while not parentStack.isEmpty() or node ≠ null
if node ≠ null then
visit(node)
if node.right ≠ null then
parentStack.push(node.right)
node = node.left
else
node = parentStack.pop()
You'll have to tweak this a bit in order to get it to return a list of the nodes, but the idea behind walking the tree is all there.

insertion binary search tree in C

I've been stuck on the insertion part of the binary search tree. I get so confused with nested structs. The basic idea of this program is to create a bst that is able to hold names and double values which get stored by value (obviously).
Example: I want to store
Jane 3.14
John 3.233
Luke 6.4
Mike 1.4
so the bst would look like
3.14
/ \
1.4 3.233
\
6.4
however I'm having trouble with the insertHelper recursion portion of the code. The hash table is a bonus part of the code that I'll try implementing at a later time. Thank you for your help!
typedef struct name_val // holds name and value
{
char *name;
double value;
}NAME_VAL;
typedef struct node //binary search tree
{
NAME_VAL *nV;
struct node *left;
struct node *right;
}NODE;
struct tmap_struct //handle for bst and hashtable
{
int nL; //nodes on left
int nR; //nodes on right
NODE *root;
NODE **table;
};
int tmap_insert(TMAP_PTR hashTree, char * name, double val)
{
if(hashTree->root == NULL)
{
NODE *bst = (NODE *)malloc(sizeof(NODE));
NAME_VAL *root = (NAME_VAL *)malloc(sizeof(NAME_VAL));
bst->nV = root;
bst->nV->value = val;
strcpy(bst->nV->name, name);
hashTree->root = bst;
hashTree->nL = 0;
hashTree->nR = 0;
}
else
insertHelper(hashTree->root, val, name);
}
void insertHelper(TMAP_PTR hashTree, int val, char * name)
{
if(val < hashTree->root->nV->value)
{
if(hashTree->root->left == NULL)
{
hashTree->root->left = (NODE *)malloc(sizeof(NODE));
hashTree->root->left->nV = (NAME_VAL *) malloc(sizeof(NAME_VAL));
strcpy(hashTree->root->left->nV->name, name);
hashTree->root->nV->value = val;
(hashTree->nL)++;
}
else
insertHelper(hashTree->root->left, val, name);
}
else
{
if(hashTree->root->right == NULL)
{
hashTree->root->right = (NODE *)malloc(sizeof(NODE));
hashTree->root->right->nV = (NAME_VAL *)malloc(sizeof(NAME_VAL));
strcpy(hashTree->root->left->nV->name,name);
hashTree->root->nV->value = val;
(hashTree->nR)++;
}
else
insertHelper(hashTree->root->right, val, name);
}
}
I doubt this compiles. Is that the problem you're having?
From what I can see, you have declared insertHelper with the wrong type for its first parameter. It should take NODE* values, not TMAP_PTR values. That's because you always call it with nodes out of your tree.
So the first part of the function should look like this:
void insertHelper(NODE *node, int val, char * name)
{
if(val < node->nV->value)
{
if(node->left == NULL)
{
node->left = (NODE *)malloc(sizeof(NODE));
node->left->nV = (NAME_VAL *) malloc(sizeof(NAME_VAL));
strcpy(node->left->nV->name, name);
node->left->nV->value = val;
}
else
insertHelper(node->left, val, name);
}
//.....
Note that I removed the line:
(hashTree->nR)++;
It hardly even makes sense to track this information, unless maybe you do it at the node level.
But if you must, you could have insertHelper recursively return a positive or negative value to indicate what side it inserted on. But that doesn't makes sense. What is it on the right of? You may have inserted it on the right of a node that was in the left half of the tree.
If you store this information on each node, you can recursively update the node above as you return from insertHelper. Maybe that's what you were trying to do. Balanced tree implementations do something similar - AVL trees store the maximum depth of the tree at a node and use that to do branch rotations for rebalancing.
You'll have to adapt mine(It's almost standard C besides the unneeded template and class), but it's a similar algorithm: (I believe, I didn't look at any source for my own purposes.)
template<typename T>
class BST {
protected:
typedef struct node_t {
struct node_t * dir[2];
T data;
} node;
node * root;
void insert_node(node * active_node, T data){ //call with node *root;
int next = data < active_node->data ? 0 : 1;
if(active_node->dir[next] == NULL){
active_node->dir[next] = new node;
active_node->dir[next]->dir[0] = NULL;
active_node->dir[next]->dir[1] = NULL;
active_node->data = data;
} else
insert_node(active_node->dir[next], data);
}
public:
BST() : root(new node){root->dir[0] = NULL; root->dir[1] = NULL; root->data = 0;}
~BST(){}
}

Resources