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;
}
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.
I have a problem with a binary tree. In my code i'm planing to implement functions like adding, deleting and printing. While Adding and printing works fine, im having troubles with deleting. My thoughts - problem is in pointers. I'm adding through 2 pointers and deleting with 1, but i cant figure out how to get it to work. Please help.
#include <stdio.h>
#include <stdlib.h>
#include "bintree.h"
void paste_node(Tree ** tr, int x)
{
Tree *tree_bin;
if ((*tr) == NULL) {
tree_bin = (Tree *) malloc(sizeof(Tree));
tree_bin->item = x;
tree_bin->lchild = tree_bin->rchild = NULL;
*tr = tree_bin;
return;
}
if (x < (*tr)->item) {
paste_node(&((*tr)->lchild), x);
} else {
paste_node(&((*tr)->rchild), x);
}
}
Tree * minimum(Tree *tr)
{
if (tr->lchild == NULL) return tr;
return minimum(tr->lchild);
}
void delete_node(Tree ** tr, int num)
{
if (tr == NULL) return;
if (num < tr->item)
tr->lchild = delete_node(tr->lchild, num);
else if (num > tr->item)
tr->rchild = delete_node(tr->rchild, num);
else {
if (tr->lchild == NULL) {
Tree *tree_bin = tr->rchild;
free(tr);
return;
}
else if (tr->rchild == NULL) {
Tree *tree_bin = tr->lchild;
free(tr);
return;
}
Tree *tree_bin = minimum(tr->rchild);
tr->item = tree_bin->item;
tr->rchild = delete_node(tr->rchild, tree_bin->item);
}
return;
}
void print_tree(Tree *tr, int depth)
{
if (tr != NULL) {
print_tree(tr->lchild, depth + 1);
for(int i = 0; i < depth; ++i) printf(" ");
printf("%d<\n", tr->item);
print_tree(tr->rchild, depth + 1);
}
}
int check_node(Tree **tr, int x) {
if ((*tr) == NULL) {
return 1;
}
if (x < (*tr)->item) {
check_node(&((*tr)->lchild), x);
} else if (x == (*tr)->item) {
return -1;
} else {
check_node(&((*tr)->rchild), x);
}
}
You can't simply delete a node of a binary tree. You can delete a leaf easily enough, just set the parent's lchild or rchild partner to null. But you can't delete an internal node without also deleting all its children. What you can do is rotate the node so that the left child (or right child) becomes the root of the sub-tree, and the root becomes a child. The reattach the new sub-tree root to the tree. Repeat until finally the node you wish to delete becomes a leaf, and remove it.
I am having trouble getting the element from the binary tree at a specific index. The function that i am having trouble with is generic tree_get_at_index(tree_node* t, int index) {
The assignment asks me to find the element at a particular index in a binary tree. For example the 0 index should return the lowest element in the binary tree and the index = treesize should return the largest element in the tree. i have a size function in my tree which works correctly but i cannot get the indexing to work for some reason. any help would be appreciated. thank you
Right now i am getting seg fault after the tree runs once.
#include "tree.h"
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
/* Memory Management */
/* This constructor returns a pointer to a new tree node that contains the
* given element.*/
tree_node* new_tree_node(generic e) {
/*TODO: Complete this function!*/
tree_node* to_return = malloc(sizeof(tree_node));
to_return->element = e;
to_return->left = NULL;
to_return->right = NULL;
return to_return;
}
/* This function is expected to free the memory associated with a node and all
* of its descendants.*/
void free_tree(tree_node* t) {
/*TODO: Complete this function!*/
if (t != NULL){
free_tree(t->left);
free_tree(t->right);
free(t);
}
}
/* End Memory Management */
/* Tree Storage and Access */
bool tree_contains(tree_node* t, generic e) {
/*TODO: Complete this function!*/
/*
if (t == NULL || t->element != e) {
return false;
}
else if (t->element == e) {
return true;
}
return tree_contains(t,e);
}
*/
if(t == NULL )
return false;
else if(t->element == e)
return true;
else if (e<t->element)
return tree_contains(t->left,e);
else
return tree_contains(t->right,e);
}
tree_node* tree_add(tree_node* t, generic e) {
/*TODO: Complete this function!*/
if(t==NULL)
t = new_tree_node(e);
else if(e == t->element)
return t;
else if(e > (t->element))
{
t->right = tree_add(t->right,e);
}
else if(e < (t->element))
{
t->left = tree_add(t->left,e);
}
return t;
}
tree_node* tree_remove(tree_node* t, generic e) {
/*TODO: Complete this function!*/
if (t == NULL) return t;
else if (e < t->element)
t->left = tree_remove(t->left, e);
else if (e > t->element)
t->right = tree_remove(t->right, e);
else
{
if (t->left == NULL)
{
tree_node *temp = t->right;
free(t);
return temp;
}
else if (t->right == NULL)
{
tree_node *temp = t->left;
free(t);
return temp;
}
else {
tree_node* current = t->right;
tree_node* temp = t->right;
while (current->left != NULL)
current = current->left;
t->element = current->element;
while (temp->left->left != NULL)
temp = temp->left;
temp->left = current->right;
free(current);
}
}
return t;
}
/* End Tree Storage and Access */
/* Size and Index */
/* Return the size of the tree rooted at the given node.
* The size of a tree is the number of nodes it contains.
* This function should work on subtrees, not just the root.
* If t is NULL, it is to be treated as an empty tree and you should
* return 0.
* A single node is a tree of size 1.*/
int tree_size(tree_node* t) {
/*TODO: Complete this function!*/
if (t==NULL)
return 0;
else
return(tree_size(t->left) + 1 + tree_size(t->right));
}
/* Return the element at the given index in the given tree.
* To be clear, imagine the tree is a sorted array, and you are
* to return the element at the given index.
*
* Assume indexing is zero based; if index is zero then the minimum
* element should be returned, for example. If index is one then
* the second smallest element should bereturned, and so on.*/
generic tree_get_at_index(tree_node* t, int index) {
//assert(index >=0 && index < tree_size(t));
/*TODO: Complete this function!*/
//tree_node* new_node = t;
// int min = 0;
// int max = tree_size(t);
// int current = (min+max)/2;
int current = index;
printf("tree size: %d \n", tree_size(t));
//while( new_node != NULL){
if(current == (tree_size(t)-1)){
return t->element;
printf("index = tree size \n");
}
else if(index < (tree_size(t->left))){
//current--;
return tree_get_at_index(t->left, index);
printf("index < tree size \n"); //= new_node->right;
}
else if(index > (tree_size(t->left))){
return tree_get_at_index(t->right, index);
printf("index > tree size \n");
}
return t->element;
//return (generic)0;
}
/* End Size and Index */
We will try filling a virtual array, as you know the size of each subtree you could skip the indexes
generic tree_get_at_index(tree_node* t, int index) {
// sanity check
assert(t);
assert(index > 0);
int leftCount=tree_size(t->left);
if(index < leftCount ) {
// good chance that the node we seek is in the left children
return tree_get_at_index(t->left, index);
}
if(index==leftCount) {
// looking at the "middle" of the sub tree
return t->element;
}
// else look at the right sub tree as it was its own array
return tree_get_at_index(t->right, index - leftCount - 1);
}
generic tree_get_at_index(tree_node* t, int index) {
assert(index >=0 && index <= tree_size(t));//I don't know how you define the tree_size function,but,according to the "if" below,you need to add equal mark
printf("tree size: %d \n", tree_size(t));
//while( new_node != NULL){
if(index == tree_size(t)){
return t->element;
}
else if(index <= tree_size(t->left)){//I think you miss the equal situation here
//current--;
return tree_get_at_index(t->left, index); //= new_node->right;
}
else /*if(index > tree_size(t->left))*/{//do not need any condition here
return tree_get_at_index(t->right, index);
}
// return t->element; //unnecessary
//return (generic)0;
}
I created a linked list and then used the following search function to get the position of the data field,but it returns the value as the last element of the linked list.I am unable to guess why
int search(struct node *curr,int d,int i)
{
if (!(curr-1))
return(0);
if (curr->data == d)
return i;
else
{
i++;
search(curr->link,d,i);
}
}
I used the following statement to control it from main:
m=search(first,data,i) //here first is the pointer to first element to first element and data is element to search
if (!(curr-1))
Why -1?
else
{
i++;
search(curr->link,d,i);
}
You have forgotten the return statement. Otherwise, the return value is undefined. Then, your recursive search function might look like:
int search(struct node *curr, int d, int i)
{
if (curr == NULL)
return 0; /* If 1 <= i <= n */
else if (curr->data == d)
return i;
else
return search(curr->link, d, i + 1);
}
Why recursion? You learn bad habits.
int search(struct node* curr, int d, int i)
{
if (NULL == curr)
{
return 0;
}
i = 1;
while(curr->data != d)
{
if (NULL != curr->link)
{
curr = curr->link;
++i;
}
else
{
return 0;
}
}
return i;
}
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.