I am writing a function to check whether a tree is a perfect binary tree and here is my code:
#include "binary_trees.h"
/**
* binary_tree_is_perfect - checks if a binary tree is perfect
* #tree: is a pointer to the root node of the tree to check
*
* Return: If the tree is perfect, it returns 1. Otherwise, it
* returns 0.
*/
int binary_tree_is_perfect(const binary_tree_t *tree)
{
int check, depth, level;
if (tree == NULL)
return (0);
level = 0;
depth = find_depth_left(tree);
check = isPerfect(tree, depth, level);
return (check);
}
/**
* find_depth_left - finds the depth of the left most leaf
* in a binary tree
* #tree: is a pointer to the tree to measure the left most
* depth
*
* Return: The depth of the left most node
*/
int find_depth_left(const binary_tree_t *tree)
{
if (!tree->left)
return (0);
return (1 + find_depth_left(tree->left));
}
/**
* isPerfect - helper function to find if a binary tree is perfect
* #depth: this is the left most depth of the tree
* #level: this is the level where to the check is happening
*
* Return: If the tree is perfect, it returns 1. Otherwise, it
* returns 0.
*/
int isPerfect(const binary_tree_t *tree, int depth, int level)
{
if (!tree->left && !tree->right)
return (depth == (level + 1));
if (!tree->left || !tree->right)
return (0);
return (isPerfect(tree->left, depth, level + 1) &&
isPerfect(tree->right, depth, level + 1));
}
My logic: I will find the left most leaf node of the tree (this is just my choice), then I will check whether the nodes will have two children or none with isPerfect function.
But for every tree I input, I get 0 (meaning the tree is not perfect). This happens even if the tree is a perfect binary tree. Where did my logic go wrong?
First the code was well thought out.
The internal (recursive) functions work on a non-null node.
That would be fine for a OOP, object oriented programming, language, as then
the function could be a member function on the node class binary_tree_t.
However here it led to difficulty: find_depth on a single node tree would logically be 1, not 0.
You could write it with accepting tree parameters as null.
Then level and depth coincide.
bool binary_tree_is_perfect(const binary_tree_t *tree)
{
int depth = find_depth_left(tree);
int level = 0;
bool check = isPerfect(tree, depth, level);
return check;
}
int find_depth_left(const binary_tree_t *tree)
{
if (!tree)
return 0;
return 1 + find_depth_left(tree->left);
}
bool isPerfect(const binary_tree_t *tree, int depth, int level)
{
if (!tree)
return level == depth;
if (!tree->left != !tree->right)
return false;
return isPerfect(tree->left, depth, level) &&
isPerfect(tree->right, depth, level);
}
So it was a semantic (=in meanding) difference between level and depth.
For the logic it would have been better to use one variable: expectedDepth.
bool binary_tree_is_perfect(const binary_tree_t *tree)
{
int expectedDepth = find_depth_left(tree);
bool check = isPerfect(tree, expectedDepth);
return check;
}
int find_depth_left(const binary_tree_t *tree)
{
return !tree ? 0 : 1 + find_depth_left(tree->left);
}
bool isPerfect(const binary_tree_t *tree, int expectedDepth)
{
if (!tree)
return 0 == expectedDepth;
if (!tree->left != !tree->right)
return false;
return expectedDepth >= 0 &&
isPerfect(tree->left, exoectedDepth - 1l) &&
isPerfect(tree->right, expectedDepth - 1);
}
expectedDepth >= 0 && is probably not needed as you took the expected depth from the left most leaf, as then the left subtree's isPerfect will return false. Interesting is it not?
Related
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 can I find using C if a binary search tree is too tall relatively fast (most of the time)?
To be more specific , lets say I need to find if a tree has a height of at least 10 ,without having to search the whole tree most of the time.
(This is possible because I expect most of the input to be binary search trees which have a heigh greater than 10.)
If there are no preconditions about the structure of the tree, there's no other way but checking one side of the tree, then the other.
int check_depth(struct tree *root, int depth)
{
if (!root) {
return 0;
} else if (depth <= 1) {
return 1;
} else {
return check_depth(root->left, depth-1) ||
check_depth(root->right, depth-1);
}
}
This is an example of a simple algorithm that returns true as soon as it's found a branch longer than 10.
#include <stdbool.h>
#include <stdio.h>
typedef struct _node
{
int data;
struct _node *l, *r;
}
node;
node *tree; // some tree
...
bool is_too_tall(node *node, int depth, int max_depth)
{
if (node == NULL)
return false;
if (depth > max_depth)
return true;
return is_too_tall(node->l, depth + 1, max_depth)
|| is_too_tall(node->r, depth + 1, max_depth);
}
int main()
{
if (is_too_tall(tree, 1, 10))
puts("Tree is too tall");
}
I think depth first search is the best option for this algorithm (as opposed to breadth first search because it is faster and simpler.
So i've got this problem where I'm supposed to find the level of an element in a tree. Nothing seems to work out so im reaching out here for help.
This is what i've got so far. The problem here is that the 4th assert, where the returned level is supposed to be 2, doesnt work and the assert is alerted. I've thought of maybe trying to not do it recursivly, but how could that be done?
int findElementLevel(const BSTree tree, const int element) {
int level = 0;
if (tree == NULL) {
return -1;
}
if (tree->data == element) {
return level;
}
if (element < (tree)->data) {
level++;
findElementLevel(tree->left, element);
return level;
}
if (element > (tree)->data) {
level++;
findElementLevel(tree->right, element);
return level;
}
}
void testNewTree(void) {
BSTree tree = emptyTree();
assert(isEmpty(tree));
int arr[5] = {3,2,5,1,4}, i;
for (i = 0; i < 5; i++)
{
insertSorted(&tree, arr[i]);
}
assert(findElementLevel(tree, 3) == 0);
assert(findElementLevel(tree, 2) == 1);
assert(findElementLevel(tree, 5) == 1);
assert(findElementLevel(tree, 1) == 2);
assert(findElementLevel(tree, 4) == 2);
}
The function always starts from the declaration of the local variable level that is set to 0.
int findElementLevel(const BSTree tree, const int element) {
int level = 0;
This value that is 0 (or 1 due to its increment in a current recursive function call) )is returned in case when the target element is found in any actual level
if (tree->data == element) {
return level;
}
You have to accumulate levels.
A recursive function can be defined for example the following way
int findElementLevel(const BSTree tree, const int element) {
if (tree == NULL) {
return -1;
}
else if ( element < tree->data ) {
int level = findElementLevel(tree->left, element);
return level == -1 ? level : level + 1;
}
else if ( tree->data < element ) {
int level = findElementLevel(tree->right, element);
return level == -1 ? level : level + 1;
}
else {
return 0;
}
}
Pay attention to that the qualifier const for the second parameter does not make great sense because the function deals with a copy of the value of the supplied argument. The function can be declared just like
int findElementLevel(const BSTree tree, int element);
This function is easier and shorter to write iteratively than recursively. The code is just:
int findElementLevel(const BSTree tree, const int element)
{
for (int level = 0; tree; ++level)
{
if (tree->data == element)
return level;
tree = tree->data < element ? tree->left : tree->right;
}
return -1;
}
With explanation, it is:
int findElementLevel(const BSTree tree, const int element)
{
/* Use a loop to process each level. We start counting levels at zero and
increment on each iteration. We continue as long as there is more of
the tree to explore ("tree" evaluates as true, i.e., non-null), or jump
out of the loop with a return if the target element is found.
*/
for (int level = 0; tree; ++level)
{
// If we found the target, return the level it is on.
if (tree->data == element)
return level;
/* Otherwise, descend to the left or the right according to which
side the target element must be on.
*/
tree = tree->data < element ? tree->left : tree->right;
}
/* If we reached the end of the tree without finding the element, return
-1.
*/
return -1;
}
How do I call a function on every node in a binary tree when using breadth-first tree traversal? Furthermore, the function needs a parameter that tells it if the current node is the first node of the current level.
I've tested my code and it doesn't seem to do it right, one node out of two is considered as the first one on every level. Here is the code:
int btree_level_count(t_btree *root)
{
int lvl_left;
int lvl_right;
if (!root)
return (0);
lvl_left = btree_level_count(root->left);
lvl_right = btree_level_count(root->right);
return (1 + lvl_left > lvl_right ? lvl_left : lvl_right);
}
void btree_applyf(t_btree *root, int lvl[2], int f_elt, void (*applyf)(void *item, int lvl, int is_first_elem))
{
if (!root)
return ;
if (lvl[0] == lvl[1])
applyf(root->item, lvl[0], f_elt);
else
{
lvl[1]++;
btree_applyf(root->left, lvl, 1, applyf);
btree_applyf(root->right, lvl, 0, applyf);
}
}
void btree_apply_by_level(t_btree *root, void (*applyf)(void *item, int current_level, int is_first_elem))
{
int height;
int lvl[2];
if (!root)
return ;
height = btree_level_count(root);
lvl[0] = 0;
lvl[1] = 0;
while (lvl[0] < height)
{
btree_applyf(root, lvl, 1, applyf);
lvl[0]++;
}
}
I use an arbitrary limit on the number of parameters per function hence the array to represent both the level and the current level.
i am having a normal binary tree that i am trying to apply iterative deepening depth first search on using c :
struct node {
int data;
struct node * right;
struct node * left;
};
typedef struct node node;
and i am using a function to insert nodes into tree, now i need to implement the search function to be something like this:
function search(root,goal,maxLevel)
so it search using depth first search but to a specific max level then stop
that was my first try,it doesn't work :
currentLevel = 0;
void search(node ** tree, int val, int depth)
{
if(currentLevel <= depth) {
currentLevel++;
if((*tree)->data == val)
{
printf("found , current level = %i , depth = %i", currentLevel,depth);
} else if((*tree)->left!= NULL && (*tree)->right!= NULL)
{
search(&(*tree)->left, val, depth);
search(&(*tree)->right, val, depth);
}
}
}
please help, thanks ...
You never stop...
node *search(node ** tree, int val, int depth)
{
if (depth <= 0)
{
return NULL; // not found
}
if((*tree)->data == val)
{
return *tree;
}
if((*tree)->left)
{
node * left = search(&(*tree)->left, val, depth - 1);
if (left) return left; // found
}
if((*tree)->right)
{
node * right = search(&(*tree)->left, val, depth - 1);
return right; // whatever is result of right
}
return NULL; // not found
}
The global variable won't work for this. You want to have something like
void search(node ** tree, int val, int remainingDepth) {
if (remainingDepth == 0) return;
then
search(&(*tree)->left, val, remainingDepth - 1);
search(&(*tree)->right, val, remainingDepth - 1);
You probably also want to check left & right for null separately, as each could be independently null.