Finding the deepest level left leaf node in a binary search tree - c++

Given a Binary Tree, find the deepest leaf node that is left child of its parent. For example, consider the following tree. The deepest left leaf node is the node with value 9.
1
/ \
2 3
/ / \
4 5 6
\ \
7 8
/ \
9 10
The answer is 9.
I developed the following code for this:
int maxlevel = 0;
Node *newNode(int data)
{
Node *temp = new Node;
temp->val = data;
temp->left = temp->right = NULL;
return temp;
}
Node * root;
Node * maxi = NULL;
int getlevel (Node * treeroot,int level, Node * foo)
{
if (treeroot == NULL)
return -1;
else if (treeroot->val == foo->val)
return level+1;
else
{
int downlevel = getlevel(treeroot->left,level+1,foo);
if (downlevel != -1)
return downlevel;
else
downlevel = getlevel(treeroot->right,level+1,foo);
return downlevel;
}
}
void foo(Node * temp)
{
// Base case
if (temp == NULL)
return;
Node * prev;
if (temp->left != NULL)
{
prev = temp;
foo(temp->left);
}
if (prev->left != NULL)
{
if (temp->left == NULL && temp->right == NULL && prev->left == temp)
{
int ind = getlevel(root,0,temp);
if (ind > maxlevel)
{
maxlevel = ind;
maxi = temp;
}
}
}
foo(temp->right);
return;
}
Here, foo is the actual function which determines the deepest left leaf in a tree. getlevel is a function which gets the level of a node in a tree. newNode is a function which allocates a new node.
When I try giving this input tree, it says the leaf is not present. Is there something wrong with my logic?
Thanks!

I think you could simplify this a little by passing the current level and a flag indicating whether the current node is a left or right child into each call...
Something like this:
int maxLevel = 0;
Node* maxNode = null;
void findDeepestLeftNode(Node* node, int level, bool isLeftChild) {
bool isLeaf = true;
if (node->left != null) {
isLeaf = false;
findDeepestLeftNode(node->left, level + 1, true);
}
if (node->right != null) {
isLeaf = false;
findDeepestLeftNode(node->right, level + 1, false);
}
if (isLeaf && isLeftChild && level > maxLevel) {
maxLevel = level;
maxNode = node;
}
}
Then just call it with:
findDeepestLeftNode(root, 0, false);
Assumes the root is not null.

Related

Problem with insertion in Binary Search Tree

I have written a code for insertion in Binary Search Tree and its traversal.
class node
{
public:
int data;
node *left;
node *right;
};
node* createNode(int value)
{
node *temp = new node;
temp->data = value;
temp->left = NULL;
temp->right = NULL;
return temp;
}
node *start = NULL;
void insertNode(int val)
{
if (start == NULL)
{
start = createNode(val);
return;
}
node *temp = start;
while ((temp->left != NULL) && (temp->right != NULL))
{
if (val < temp->data)
{
temp = temp->left;
}
else if (val > temp->data)
{
temp = temp->right;
}
else
{
cout << "Already exists in tree\n";
return;
}
}
if (val < temp->data)
{
temp->left = createNode(val);
return;
}
else
{
temp->right = createNode(val);
return;
}
}
void inorder(node *root)
{
if (root != NULL)
{
inorder(root->left);
printf("%d \n", root->data);
inorder(root->right);
}
}
It does not work fine on some test cases.
For example, if insert 15, 25 and then 35, and then traverse the tree, it only prints 15 and 25.
I am not able to find out the problem in the code. What is the issue with my insertion logic?
Let's go through the behavior -
you insert the 15. if (start == NULL)
this check creates the start node. Now there is a start node with value 15 and left and right as NULL.
you insert 25. (temp->left != NULL) && (temp->right != NULL)
this turns out to be false.
(val < temp->data) this check creates a right node.
you insert 35. (temp->left != NULL) && (temp->right != NULL)
still turns out to be false.
(val < temp->data) this check creates a right node (replacing the current right node). Which is not right.
You need to correct the while loop condition here.

How do I access a pointer from within a nested class?

This class's purpose is to emulate the functions of a Binary Search Tree. In the below code, I am trying to adapt it from a struct and a bunch of functions, into a wrapper class, called BST. One thing I am not sure of however, is how to access 'root' from within the node struct. Root is currently declared within the BST class.
class bst
{
public:
struct Node
{
public:
int data;
struct Node *left;
struct Node *right;
Node* FindMin(Node* root)
{
while(root->left != NULL) root = root->left;
return root;
}
Node* Insert(Node *root,int data)
{
if(root == NULL) {
root = new Node();
root->data = data;
root->left = root->right = NULL;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
else if(data <= root->data)
root->left = Insert(root->left,data);
else
root->right = Insert(root->right,data);
return root;
}
Node* Delete(struct Node *root, int data)
{
if(root == NULL) return root;
else if(data < root->data) root->left = Delete(root->left,data);
else if (data > root->data) root->right = Delete(root->right,data);
//Value found
else {
// Case 1: No child
if(root->left == NULL && root->right == NULL)
{
delete root;
root = NULL;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
//Case 2: One child
else if(root->left == NULL)
{
struct Node *temp = root;
root = root->right;
delete temp;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
else if(root->right == NULL)
{
struct Node *temp = root;
root = root->left;
delete temp;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
// case 3: 2 children
else
{
struct Node *temp = FindMin(root->right);
root->data = temp->data;
root->right = Delete(root->right,temp->data);
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
}
return root;
}
//# of Nodes in tree
void size(Node *root)
{
//Check if end
if(root == NULL) return;
//Not end
else
{
bstSize = bstSize + 1;
size(root->left); //Visit left subtree
size(root->right); // Visit right subtree
}
}
void height(Node *root, int temp)
{
//Check if end
if(root == NULL)
{
if(temp > bstHeight)
{
bstHeight = temp;
}
return;
}
//Not end
else
{
temp = temp + 1;
height(root->left, temp); //Visit left subtree
height(root->right, temp); // Visit right subtree
}
}
//Function to visit nodes in Inorder
void show()
{
if(root == NULL) return;
show(root->left); //Visit left subtree
printf("%d ",root->data); //Print data
show(root->right); // Visit right subtree
}
void check(Node *root)
{
//End of a 'branch'
if(root == NULL) return;
int value = 0;
value = root->data;
//Checking left subtree
if(value < root->left->data)
{
//Tree is NOT valid
valid = 0;
}
//Checking right subtree
if(value > root->right->data)
{
//Tree is NOT valid
valid = 0;
}
check(root->left); //Visit left subtree
printf("%d ",root->data); //Print data
//check(root->right); // Visit right subtree
}
};
Node* root = NULL;
};
Specifically, in the show function. It's not as simple as putting it into Node with the rest of the functions, as root needs to be unique, and new Node is called at least once. Show will not compile in the current state, and I'm not sure where to proceed from here.
Though the comment says everything, let me give an additional hint:
When you want to keep your code as similar as possible to what you have now, try to add a constructor to the Node class that expects a pointer or reference (preferable) to the root and check, that each time you create a Node, you give the root to the constructor.
By the way, it might even be a better approach to look at some simple Node-based data structure implementations in C++, for example in the thread
Simple linked list in C++

AVL Tree Traversal from outside Tree class

I am having some trouble with a Tree comparison program I am writing in C++. I am trying to traverse a tree to compare elements in another tree from a comparator class, and I am getting an error that says that I cannot access root in the AVL tree class. The error I am getting is:'class avlTree' has no member named 'root.' Below is my code for the method in question, and after that is the AVL Tree class. I am beginning to wonder if I should pass in the second tree to be compared in the method call to a method within the AVL Tree class, and just traverse the tree, and call to the second tree from within the Tree class. I am very much a beginner at C++, so I apologize in advance for any confusion and/or poor style.
Method
void findCommon(){
if(tree.root == NULL){
return;
}
findCommon(tree.root->left);
if (tree2.find(tree.root) == true){
cout<<tree.root->data<<" ";
}
findCommon(tree.root->right);
}
AVL Tree Class
#include<iostream>
#include<cstdio>
#include<sstream>
#include<algorithm>
#include<string>
#define pow2(n) (1 << (n))
using namespace std;
/*
* Node Declaration
*/
struct avl_node
{
string data;
struct avl_node *left;
struct avl_node *right;
}*root;
/*
* Class Declaration
*/
class avlTree
{
public:
avlTree()
{
root = NULL;
}
/*
* Height of AVL Tree
*/
int height(avl_node *temp)
{
int h = 0;
if (temp != NULL)
{
int l_height = height (temp->left);
int r_height = height (temp->right);
int max_height = max (l_height, r_height);
h = max_height + 1;
}
return h;
}
/*
* Height Difference
*/
int diff(avl_node *temp)
{
int l_height = height (temp->left);
int r_height = height (temp->right);
int b_factor= l_height - r_height;
return b_factor;
}
/*
* Right- Right Rotation
*/
avl_node* rr_rotation(avl_node *parent)
{
avl_node* temp;
temp = parent->right;
parent->right = temp->left;
temp->left = parent;
return temp;
}
/*
* Left- Left Rotation
*/
avl_node* ll_rotation(avl_node *parent)
{
avl_node* temp;
temp = parent->left;
parent->left = temp->right;
temp->right = parent;
return temp;
}
/*
* Left - Right Rotation
*/
avl_node* lr_rotation(avl_node *parent)
{
return parent;
}
/*
* Right- Left Rotation
*/
avl_node* rl_rotation(avl_node *parent)
{
return parent;
}
/*
* Balancing AVL Tree
*/
avl_node* balance(avl_node *temp)
{
int bal_factor = diff (temp);
if (bal_factor > 1)
{
if (diff (temp->left) > 0)
temp = ll_rotation (temp);
else
temp = lr_rotation (temp);
}
else if (bal_factor < -1)
{
if (diff (temp->right) > 0)
temp = rl_rotation (temp);
else
temp = rr_rotation (temp);
}
return temp;
}
/*
* Insert Element into the tree
*/
avl_node* insert(avl_node *root, string value)
{
if (root == NULL)
{
root = new avl_node;
root->data = value;
root->left = NULL;
root->right = NULL;
return root;
}
else if (value < root->data)
{
root->left = insert(root->left, value);
root = balance (root);
}
else if (value >= root->data)
{
root->right = insert(root->right, value);
root = balance (root);
}
return root;
}
avl_node * minValueNode(avl_node* node)
{
avl_node* current = node;
/* loop down to find the leftmost leaf */
while (current->left != NULL)
current = current->left;
return current;
}
bool find(avl_node* root, string data)
{
// STEP 1: PERFORM STANDARD BST DELETE
if (root == NULL)
return false;
// If the data to be deleted is smaller than the
// root's data, then it lies in left subtree
if ( data < root->data ){
return find(root->left, data);
}
// If the data to be deleted is greater than the
// root's data, then it lies in right subtree
else if( data > root->data ){
return find(root->right, data);
}
else
{
return true;
}
}
// Recursive function to delete a node with given data
// from subtree with given root. It returns root of
// the modified subtree.
avl_node* pick(avl_node* root, string data)
{
// STEP 1: PERFORM STANDARD BST DELETE
if (root == NULL)
return root;
// If the data to be deleted is smaller than the
// root's data, then it lies in left subtree
if ( data < root->data )
root->left = pick(root->left, data);
// If the data to be deleted is greater than the
// root's data, then it lies in right subtree
else if( data > root->data )
root->right = pick(root->right, data);
// if data is same as root's data, then This is
// the node to be deleted
else
{
// node with only one child or no child
if( (root->left == NULL) || (root->right == NULL) )
{
avl_node *temp = root->left ? root->left :
root->right;
// No child case
if (temp == NULL)
{
temp = root;
root = NULL;
}
else // One child case
*root = *temp; // Copy the contents of
// the non-empty child
free(temp);
}
else
{
// node with two children: Get the inorder
// successor (smallest in the right subtree)
avl_node* temp = minValueNode(root->right);
// Copy the inorder successor's data to this node
root->data = temp->data;
// Delete the inorder successor
root->right = pick(root->right, temp->data);
}
}
// If the tree had only one node then return
if (root == NULL)
return root;
// STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
//root->height = 1 + max(height(root->left),
// height(root->right));
// STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to
// check whether this node became unbalanced)
balance(root);
return root;
}
void inOrder(avl_node *root){
if(root == NULL){
return;
}
inOrder(root->left);
cout<<root->data<<" ";
inOrder(root->right);
}
};

Where is the flaw in my binary tree insertion logic?

My solution is like
/*
Node is defined as
typedef struct node
{
int data;
node * left;
node * right;
}node;
*/
node * insert (node * root, int value)
{
bool inTreeAlready = false;
node * cur = root;
while(cur != NULL)
{
if(cur->data < value)
cur = cur->right;
else if(cur->data > value)
cur = cur->left;
else
{
inTreeAlready = true;
break;
}
}
if(!inTreeAlready)
{
cur = new node;
cur->data = value;
cur->left = NULL;
cur->right = NULL;
}
return root;
}
where the prompt to the problem says you're supposed to return the root of the tree after insertion.
This is evidently wrong as the output is
Wrong Answer!
Some possible errors:
1. You returned a NULL value from the function.
2. There is a problem with your logic
3. You are printing some value from the function
which isn't very descriptive.
I've double-checked my logic and don't know what the deal is.
You didn't add the new node into the tree. Here's a modified version.
node * insert (node * root, int value)
{
bool inTreeAlready = false;
node * cur = root;
node *parent;
bool right;
while(cur != NULL)
{
parent = cur;
if(cur->data < value)
{
cur = cur->right;
right = true;
}
else if(cur->data > value)
{
cur = cur->left;
right = false;
}
else
{
inTreeAlready = true;
break;
}
}
if(!inTreeAlready)
{
cur = new node;
cur->data = value;
cur->left = NULL;
cur->right = NULL;
if(root == NULL) root = cur;
else if(right) parent->right = cur;
else parent->left = cur;
}
return root;
}

Tree structure - incorrect children

I'm trying to build simple structure in C++. It should be similar to AVL tree.
Everything is OK when I build a simple tree with three nodes in main() function.
The problem is when I try use insert() function. The first argument of this function contains information where put the value from the second argument.
Here is the code:
#include <numeric>
#include <vector>
#include <cstdio>
#include <cstdlib>
using namespace std;
struct Node {
Node* left;
Node* right;
Node* parent;
int value;
int count_leafs;
int height;
};
Node* root;
void insert2(int p, int value, Node* node, int left)
{
//printf("insert %d %d - (%d, %d) %d \n", p, value, node->left, node->right, left);
if (root == NULL) {
// creating a tree root
Node new_node;
new_node.left = NULL;
new_node.right = NULL;
new_node.parent = NULL;
root = &new_node;
root->value = value;
root->count_leafs = 1;
root->height = 1;
return;
}
if (node->left == NULL && node->right == NULL) {
// joining value to the leaf
Node new_parent;
new_parent.count_leafs = 2;
new_parent.height = 2;
new_parent.value = node->value + value;
new_parent.parent = node->parent;
new_parent.left = NULL;
new_parent.right = NULL;
Node new_leaf;
new_leaf.value = value;
new_leaf.count_leafs = 1;
new_leaf.left = NULL;
new_leaf.right = NULL;
new_leaf.height = 1;
new_leaf.parent = &new_parent;
new_parent.left = &new_leaf;
new_parent.right = node;
if (node->parent != NULL && node->parent->left != NULL && node->parent->left == node) {
printf("a");
node->parent->left = &new_parent;
}
if (node->parent != NULL && node->parent->right != NULL && node->parent->right == node) {
printf("b");
node->parent->right = &new_parent;
}
node->parent = &new_parent;
return;
}
//printf("GOTO: %d %d \n", left + node->left->count_leafs, p);
node->value += value;
node->count_leafs += 1;
if (left + node->left->count_leafs + 1 >= p) {
//printf("W left\n");
insert2(p, value, node->left, left);
} else {
//printf("W right\n");
insert2(p, value, node->right, left + node->left->count_leafs);
}
}
void insert(int p, int value)
{
insert2(p, value, root, 0);
}
int main()
{
Node new_root;
root = NULL;
new_root.value = 10;
new_root.height = 2;
new_root.count_leafs = 2;
new_root.parent = NULL;
root = &new_root;
Node left;
left.value = 6;
left.height = 1;
left.count_leafs = 1;
left.parent = root;
left.left = NULL;
left.right = NULL;
Node right;
right.value = 4;
right.height = 1;
right.count_leafs = 1;
right.parent = root;
right.left = NULL;
right.right = NULL;
root->left = &left;
root->right = &right;
// PLACE A
insert(0, 1);
// PLACE B
return 0;
}
As you see before PLACE A is building a tree with 3 nodes. It look like this in PLACE A:
10
/ \
6 4
Next, in a line between PLACE A and PLACE B, I want to add a new node. After that (in PLACE B) the tree should looks like this:
11
/ \
7 4
/ \
1 6
But I gets something like this:
11
/ \
1972250912 4
/ \
2 2
I can't figure out what is wrong. It should be the problem in insert2() function, but I can't find it.
Do you see it?
Thanks in advance for you help!
The cause of a such behavior is that you use scope variables out of the scope. You must not use the pointer that points to the scope variable out of that scope. Scope variables exists only withing the scope were they were declared. If decide to access a scope variable out of the scope, you will access some piece of stack that would have some other data overwritten that variable that would result in undefined behavior.
I mean, that you must NOT do like this:
if (root == NULL)
{
Node new_node;
root = &new_node;
return;
}
You may use operator new to create a new instance of struct Node in the heap and use it later.
if (root == NULL)
{
root = new Node;
return;
}
But you have to delete this node later. Or you may use smart pointers, see this.
Read this and this for more information.
The code below do just what you expected. However it does not delete created nodes that would result in memory leak, so this code have to be improved, but this is a separate issue.
#include <numeric>
#include <vector>
#include <cstdio>
#include <cstdlib>
using namespace std;
struct Node {
Node* left;
Node* right;
Node* parent;
int value;
int count_leafs;
int height;
};
Node* root;
void insert2(int p, int value, Node* node, int left)
{
//printf("insert %d %d - (%d, %d) %d \n", p, value, node->left, node->right, left);
if (root == NULL) {
// creating a tree root
Node* new_node = new Node;
new_node->left = NULL;
new_node->right = NULL;
new_node->parent = NULL;
root = new_node;
root->value = value;
root->count_leafs = 1;
root->height = 1;
return;
}
if (node->left == NULL && node->right == NULL) {
// joining value to the leaf
Node* new_parent = new Node;
new_parent->count_leafs = 2;
new_parent->height = 2;
new_parent->value = node->value + value;
new_parent->parent = node->parent;
new_parent->left = NULL;
new_parent->right = NULL;
Node* new_leaf = new Node;
new_leaf->value = value;
new_leaf->count_leafs = 1;
new_leaf->left = NULL;
new_leaf->right = NULL;
new_leaf->height = 1;
new_leaf->parent = new_parent;
new_parent->left = new_leaf;
new_parent->right = node;
if (node->parent != NULL && node->parent->left != NULL && node->parent->left == node) {
printf("a");
node->parent->left = new_parent;
}
if (node->parent != NULL && node->parent->right != NULL && node->parent->right == node) {
printf("b");
node->parent->right = new_parent;
}
node->parent = new_parent;
return;
}
//printf("GOTO: %d %d \n", left + node->left->count_leafs, p);
node->value += value;
node->count_leafs += 1;
if (left + node->left->count_leafs + 1 >= p) {
//printf("W left\n");
insert2(p, value, node->left, left);
}
else {
//printf("W right\n");
insert2(p, value, node->right, left + node->left->count_leafs);
}
}
void insert(int p, int value)
{
insert2(p, value, root, 0);
}
int main()
{
Node new_root;
root = NULL;
new_root.value = 10;
new_root.height = 2;
new_root.count_leafs = 2;
new_root.parent = NULL;
root = &new_root;
Node left;
left.value = 6;
left.height = 1;
left.count_leafs = 1;
left.parent = root;
left.left = NULL;
left.right = NULL;
Node right;
right.value = 4;
right.height = 1;
right.count_leafs = 1;
right.parent = root;
right.left = NULL;
right.right = NULL;
root->left = &left;
root->right = &right;
// PLACE A
insert(0, 1);
// PLACE B
return 0;
}