Is a Binary Tree Contained Within Another Binary Tree - C - c

So I just had an interview that I'm confident I screwed up royally. I had a bunch of questions thrown at me and didn't have enough time to answer the last one.
After getting all beginning questions correct, I was asked to write a function that would determine whether a binary tree b is contained within another binary tree a. I coded the question prior to that correctly, in which he asked me to write a function to determine whether two trees are equal:
int sameTree(struct node *a, struct node *b){
//both empty = TRUE
if(a == NULL && b == NULL)
return TRUE;
//both not empty, compare them
else if(a != NULL && b != NULL){
return(
a->data == b->data &&
sameTree(a->left, b->left) &&
sameTree(a->right, b->right)
);
}
//one empty, one not = FALSE
else
return FALSE;
}
Ugh. Just for clearing my conscience, again how would you determine whether tree b is inside tree a?
Thanks for any help guys.

int in(struct node* outer, struct node* inner){
if(inner == null){
return true; // say every tree contains the empty tree
} else if(outer == null){
return false;
} else if(same(outer, inner)){
return true;
} else return in(outer->left, inner) || in(outer->right, inner);
}
We must not use the OP's sameTree but rather this function:
int same(struct node* outer, struct node* inner){
return !inner || outer && outer->data == inner->data && same(outer->left, inner->left) && same(outer->right, inner->right);
}
Or, more verbosely,
int same(struct node* outer, struct node* inner){
if(inner == null){
return true;
} else if(outer == null){
return false;
} else if(outer->data == inner->data){
return same(outer->left, inner->left) && same(outer->right, inner->right);
} else return false;
}

This assumes you want the same tree with the same structure, contains in a:
For one, if b is null and a isn't, a contains b (you should check that in your last else).
Second, these aren't binary search trees (unsorted), so to check if b is inside a you should also traverse a (assuming you rename the function):
int containsTree(struct node *a, struct node *b){
//both empty = TRUE
if(a == NULL && b == NULL)
return TRUE;
//both not empty, compare them
else if(a != NULL && b != NULL){
return(
// sameTree should be changed to allow nulls, as below
sameTree(a, b)
// check recursively
|| containsTree(a->left, b)
|| containsTree(a->right, b)
);
//one empty, one not = FALSE
else
return B == NULL;

To check if tree A is contained as-is in tree B, find the node C in B such that C.data == A.data. If there is no such node, A is not contained in B. If C exists, check if A and C are equal using a modified sameTree function - one that ignores mismatches between null children of A and non-null children of C (return true if A.left/right is null).
Thanks #Kobi for the correction.

Related

The least node that is greater than or equal to a given value in AVL

I am trying to implement a function in C that will find the smallest int that is greater than or equal to a given int in an AVL. For example:
if I have an AVL tree consisting of 1,2,3,4,5,6,7 and I put in 6, it should return 6.
if I have an AVL tree consisting of 1,2,3,4,6,7 and I put in 5, it should return 6.
if none are found, return -1.
I have found a case (there could be more) where this implementation fails. If I have an AVL tree of 1,2,3,4,5,6,7 and I input 3 it incorrectly returns 4. This case occurs when the ROOT is bigger than the input. I am not sure how to fix this though. There could also be other cases — if you could let me know that would be great.
Here is my attempt:
int findLeastGreatest(Node *root, int input) {
// Never found
if (root->left == NULL && root->right == NULL && root->data < input)
return -1;
// Found
if ((root->data >= input && root->left == NULL) ||
(root->data >= input && root->left->data < input))
return root->data;
if (root->data <= input)
return findLeastGreatest(root->right, input);
else
return findLeastGreatest(root->left, input);
}
Your function has problems: you are testing too many conditions together:
Here is a simpler approach:
if the root is NULL, you should return -1;
if the root->data < input, you should just recurse on the root->right node
if root->data == input you should just return input.
otherwise, you should recurse on the left node and return the result if found, otherwise return root->data.
Here is an implementation:
int findLeastGreatest(const Node *root, int input) {
if (!root)
return -1;
if (root->data < input)
return findLeastGreatest(root->right, input);
if (root->data == input)
return input;
int value = findLeastGreatest(root->left, input);
if (value == -1)
return root->data;
else
return value;
}
If you are not required to produce a recursive version, here is a simpler version with a while loop:
int findLeastGreatest(const Node *root, int input) {
int value = -1;
while (root) {
if (root->data < input) {
root = root->right;
} else {
value = root->data;
root = root->left;
}
}
return value;
}
I find it easier to write this function in a loop. The algorithm in the pseudocode below should work. The key idea is to not assign to bound unless the condition (node.key >= key) is true, in which case you must also traverse left to look for potentially smaller keys that satisfy the same condition. Otherwise, traverse right to look for larger keys that might satisfy.
least_greatest(node, key):
bound = -1
while node != NULL:
if node.key >= key:
bound = node.key # found a bound, but it might not be the least bound
node = node.left # look for a smaller key
else:
node = node.right # look for larger keys
return bound
P.S. this function is called upper_bound in the C++ STL, and I've also seen this called "least upper bound".

Form flag with 3 nodes in a binary tree

I have a binary tree with nodes colored either in green, white or red. The function returns 1 if it finds a path of three nodes that form the italian flag, 0 otherwise. 
This is what I've tried but it gives me segmentation fault.
struct node{
char color;
struct node* left;
struct node* right;
struct node* father;
};
typedef struct node* Node;
int flag(Node v){
if(v==NULL)
return 0;
flag(v->left);
flag(v->right);
if(v->color=='W' && v->father->color=='G' && (v->left->color=='R' || v->right->color=='R'))
return 1;
}
EDIT: Thanks to all for answering. This should be the correct version
int flag(Node v){
if(v==NULL)
return 0;
if(v->left && v->father)
if(v->color=='B' && v->father->color=='V' && v->left->color=='R')
return 1;
if(v->right&& v->father)
if(v->color=='B' && v->father->color=='V' && v->right->color=='R')
return 1;
return flag(v->left) || flag(v->right);
}
The problem is probably that you call flag with invalid pointer v->left or v->right.
Probably you did not initialize with NULL the node fields.
Other problem is that if any of v->left or v->right is NULL you still try to access v->left->color in the last composed condition.
Other error is that you do not explicitly return a value in case that the last combination is false. If
v->color=='W' &&
v->father->color=='G' &&
(v->left->color=='R' || v->right->color=='R')
is false, you do not return a value at the end of the function.
You might have NULL pointers...
if(v->color=='W' && v->father->color=='G' && (v->left->color=='R' || v->right->color=='R'))
You do not check if v->left or v->right are NULL before you dereference them. For the root node also v->father could be NULL.
You should also add an else part returning 0.
Besides that:
For which purpose do you call flag(v->left) and flag(v->right) if you don't care about the return value?
int flag(Node v)
{
if(v==NULL)
return 0;
flag(v->left); // <<-- this call will return when v->left is NULL
flag(v->right); // <<-- this call will return when v->right is NULL
//so, if you come till here in case 'v' is leaf then (v->left is NULL) and (v->right is NULL)
//but you are accessing them as 'v->left->color' and 'v->right->color'
//that is accessing 'NULL->color' is bound to break.
if(v->color=='W' && v->father->color=='G' && (v->left->color=='R' || v->right->color=='R'))
return 1;
}

Find the first key bigger than X on Binary Search Tree

The successor of an element in a BST is the element's successor in the
sorted order determined by the inorder traversal. Finding the
successor when each node has a pointer to its parent node is presented
in CLRS's algorithm textbook (Introduction to Algorithms by MIT
press).
Is there a way to find the first value that is bigger than X without parent in the struct? Like:
typedef struct tree tree;
struct tree{
int value;
tree *left;
tree *right;
};
//Function:
tree *find_first_bigger(tree *t, int x){}
I tried working with:
tree *find_first_bigger(tree *t, int x){
if(t == NULL)
return NULL;
if((*t)->value > x)
find_first_bigger((*t)->left, x);
else if((*t)->value < x)
find_first_bigger((*t)->right), x);
else if((*t)->value == x){
if((*t)->right != NULL)
return tree_first_bigger((*t)->right);
else
return tree;
}
}
With this example(it's using letter but there its not a problem), if I try to search the first bigger than N(It should return me O) but it returns me N.
You have done 90% of the job.Allow me to do the remaining 10%.
Since t is a pointer to structure you should use t->left instead of (*t)->left and same applies while accessing right and value fields of the struct.
Now, Just modify your function as:
Add this as first line of your function
static tree* PTR=NULL;
Modify the second if condition as:
if(t->value > x)
{
PTR=t;
find_first_bigger(t->left, x);
}
Modify the second else if condition as:
else if(t->value == x)
{
if(t->right != NULL)
{
t=t->right;
while(t->left!=NULL)
t=t->left;
return t;
}
else return PTR;
}
Hence the correct function is
tree *find_first_bigger(tree *t, int x)
{
static tree* PTR=NULL;
if(t == NULL)
return NULL;
if(t->value > x)
{
PTR=t;
find_first_bigger(t->left, x);
}
else if(t->value < x)
find_first_bigger(t->right, x);
else if(t->value == x)
{
if(t->right != NULL)
{
t=t->right;
while(t->left!=NULL)
t=t->left;
return t;
}
else return PTR;
}
}
In the main function if pointer returned is NULL, this means that :the key itself is the largest key. Feel free for any queries.
I haven't tested this, but I think it should work. Let me know if it is wrong.
//c++ 11
#include<iostream>
using namespace std;
struct BSTNode{
int val;
BSTNode* left;
BSTNode* right;
};
int FindJustLarger(BSTNode*& node, int token, int sofarlarge){
// for invalid inputs it will return intial value of sofarlarge
// By invalid input I mean token > largest value in BST
if(node == nullptr)
return sofarlarge;
else if(node->val > token){
sofarlarge = node->val;
return FindJustLarger(node->left, token, sofarlarge);}
else
return FindJustLarger(node->right, token, sofarlarge);}
int main(){
BSTNode* head = new BSTNode{5, nullptr, nullptr};
FindJustLarger(head, 5, NULL);
delete head;
return 0;}
Some changes you can do in your code:
You have to return the values from the recursive calls
If the value is not found, return NULL. This means returning NULL if t->right == NULL on the last if.
When going to the left, if the value is not found there, the answer must be the node itself. In the case of N, it is the last node where we turn left: O. If it were P, the answer would be T itself.
After all those changes, the code should look like this:
tree *find_first_bigger(tree *t, int x){
if(t == NULL)
return NULL;
if(t->value > x) {
tree *answer = find_first_bigger(t->left, x);
if (answer != NULL)
return answer;
return t;
} else if(t->value < x) {
return find_first_bigger(t->right, x);
} else if(t->value == x) {
if (t->right != NULL)
return tree_first_bigger(t->right);
return NULL;
}
}
You can find the entire code I used to test in this gist.
In your question, you seemed to indicate that you want to find out InOrderSuccessor() of the the given value 'x'.
If 'x' does not necessarily exist in the tree, we need to change the algorithm. Given the example you provided and the problem statement, here is code for finding the next element in a BST.
The key cases are :
No greater element exists, because 'x' is the biggest.
'x' has a right child ?
YES: get left-most child of x's right sub-tree.
NO : return parent.
Key observation is that we don't update the parent pointer, whenever we go right in the tree.
tree *ptr = root;
tree *prnt = NULL;
while (ptr != NULL) {
if (x == ptr->key) {
if (ptr->right != NULL) {
return GetLeftMostChild(ptr->right);
} else {
return prnt;
}
} else if (x > ptr->key) {
ptr = ptr->right;
} else {
prnt = ptr;
ptr = ptr->left;
}
}
Here is the definition for leftMostChild()
tree *GetLeftMostChild(tree *n) {
tree *ptr = n;
while (ptr->left != NULL) {
ptr = ptr->left;
}
return ptr;
}

Issue with infinite loop in radix tree implementation

I'm having trouble with my radix tree implementation. The idea is that I create the first node, then enter a number of binary numbers. The binary numbers determine whether a left node (0) or a right node (1) is created. Once I reach the end of the binary number, I set a node to "active".
Then I search through the tree to find an active node, and output the original binary numbers again by checking in which direction I had to go to reach the active node.
Here is the complete code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int bool;
enum { false, true };
typedef struct radixNode {
bool active;
struct radixNode * pnt;
struct radixNode * l;
struct radixNode * r;
} node;
void insert(node *root, char * B) {
printf("String: %s\n", B);
printf("1st: %c", B[0]);
printf("\n\n", B);
// digit is zero so we go left
if (B[0] == '0') {
printf("till here if");
// left child doesn't exist, create it
if (root->l == NULL) {
root->l = malloc(sizeof(node));
/* if the next index in the string does NOT contain a 1 or 0,
the current index is the last index and the node is activated */
if (B[1] == 1 || B[1] == 0)
root->l->active = false;
else
root->l->active = true;
root->l->pnt = root;
root->l->l = NULL;
root->l->r = NULL;
insert(root->l,B++); // B++ removes the first digit of the string
}
// left child exists, traverse
else {
insert(root->l,B++);
}
}
// digit is one, go right
else if (B[0] == '1') {
printf("first was 1\n");
// right child doesn't exist, create it
if (root->r == NULL) {
printf("if triggered\n");
root->r = malloc(sizeof(node));
/* if the next index in the string does NOT contain a 1 or 0,
the current index is the last index and the node is activated */
if (B[1] == 1 || B[1] == 0)
root->r->active = false;
else
root->r->active = true;
root->r->pnt = root;
root->r->l = NULL;
root->r->r = NULL;
insert(root->r,B++);
}
// left child exists, traverse
else {
printf("else triggered\n");
insert(root->r,B++);
}
}
}
node * printTreeMin(node *root) {
char C[10];
/* goes left until it can't, appends 0 to string
till it can't. if node is active, print the string */
while (root->l != NULL) {
C[strlen(C)] = '0';
if (root->active == true)
printf("%s\n",C);
root = root->l;
}
return root;
}
// prints the next smallest binary number in the tree, returns the node it printed
node * printNextSmallest(node * root) {
char C[10];
// if right child exists, go there and find lowest node (after if same deal as printTreeMin() )
if (root->r != NULL) {
C[strlen(C)] = '1';
if (root->active == true)
printf("%s\n",C);
root = root->r;
while (root->l != NULL) {
C[strlen(C)] = '0';
if (root->active == true)
printf("%s\n",C);
root = root->l;
}
return root;
}
node * temp = root->pnt;
while (temp != NULL && root == temp->r) {
root = temp;
temp = temp->pnt;
}
return temp;
}
void printRadixTree(node *root) {
root = printTreeMin(root);
while (printNextSmallest(root) != NULL)
root = printNextSmallest(root);
}
void test() {
node * tree = malloc(sizeof(node));
tree->l = NULL;
tree->r = NULL;
// a)
insert(tree,"101000");
insert(tree,"10100");
insert(tree,"10110");
insert(tree,"101");
insert(tree,"1111");
// b)
printRadixTree(tree);
}
int main() {
test();
}
Here is the output:
if triggered
String: 101000
1st: 1
first was 1
if triggered
String: 101000
1st: 1
first was 1
if triggered
String: 101000
1st: 1
(and continuing ad infinitum)
Clearly I have an issue within the insert() function's recursion but considering I remove the first char of the binary number string when doing the recurrence, I don't understand how it can run infinitely.
The reason for the infinite recursion is your choice of auto-increment operator. You want the prefix, not suffix form.
insert(..., B++)
increments the pointer (stripping the first character) after calling insert.
Instead the calls should be
insert (..., ++B)
You also have problems with your active flag, and this is your culprit
if (B[1] == 1 || B[1] == 0)
I think you meant
if (B[1] == '1' || B[1] == '0')
The first form is checking for a binary zero or one, rather than an ASCII character.
The result of this is that your active flag will probably be set incorrectly for most nodes. I expect that will then cause problems when traversing the tree. In fact, active will only be set to false when you are looking at the last '0' or '1' in the string (as B[1] at that point will be the terminating '\0').
Also, with recusive routines it is always a good idea to make the base case explicit, rather than implicit. Thus, one of the first blocks of code in insert should probably be
if (B[0] != '1' && B[0] != `0`)
return;
then you can replace the else if with a simple else
if (B[0] == '0')
{
// ... go left
}
else
{
// ... go right
}

Help inserting a list of values into a binary tree..?

Well, I've been at it for a while...trying to figure out an algorithm to insert my list of random numbers into a binary tree.
This is what I have gotten so far:
NodePtr and Tree are pointers to a node
NodePtr CreateTree(FILE * fpData)
{
int in;
fscanf(fpData, "%i", &in);
Tree T = (NodePtr)malloc(sizeof(Node));
T->Left = NULL;
T->Right = NULL;
T->value = in;
while((fscanf(fpData, "%i", &in)) != EOF)
{
InsertInTree(in, T);
printf("\n %p", T);
}
return T;
}
void InsertInTree(int value,Tree T)
{
if(T == NULL)
{
T->Left = (NodePtr)malloc(sizeof(Node));
T->Left->Left = NULL;
T->Left->Right = NULL;
T->Left->value = value;
printf("\n %i ", value);
return;
}
if(T->Left == NULL)
{
InsertInNull(value, T->Left);
}
else if(T->Right == NULL)
{
InsertInNull(value, T->Right);
}
else
{
if(T->Left->Left == NULL || T->Left->Right == NULL) InsertInTree(value, T->Left);
else InsertInTree(value, T->Right);
}
}
I'm lost on what to do if the both children of a particular node are not null. What I did here works for a small amount of numbers (1,2,3,5,6) but if the list is larger it becomes unbalanced and wrong.
Is it meant to be a search-tree? I don't see any if (value < T->Value) conditions.
And you have an InsertNull (not shown). That shouldn't be necessary, 1 function should be enough.
To address your main problem, use a pointer-to-pointer parameter or, more elegant, always return a new Tree:
//untested, no balancing
Tree InsertValue(Tree t, int value)
{
if (t == null)
t = // create and return new node
else
{
if (value < t->Value)
t->Left = InsertValue(t->Left, value);
else
t->Right = InsertValue(t->Left, value);
}
return t;
}
And in CreateTree:
Tree t = InsertValue(null, in);
Since the assignment is not for a sorted tree, you can populate it in a breadth-first manner. This means the first thing inserted is always the root, the next is the first node at the next level so it looks like this:
0
1 2
3 4 5 6
Here is an article that explains it further:
http://www.cs.bu.edu/teaching/c/tree/breadth-first/
Simple insertion in a binary tree and keeping a binary tree balanced are different problems. I suggest you start with the first problem and just focus on keeping order properties correct within the tree. Your are not far from that.
Then you should have a look at classical implementations for red-black trees, well studied and efficient way of keeping trees balanced, but with a cost, it's more complex.

Resources