0% found this document useful (0 votes)
18 views

Lab Manual Tree

Uploaded by

subhash.chandra
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views

Lab Manual Tree

Uploaded by

subhash.chandra
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 43

Maximum in Binary Tree

Given a Binary Tree, find the maximum(or minimum) element in it. For example, maximum in
the following Binary Tree is 9.

In Binary Search Tree, we can find maximum by traversing right pointers until we reach the
rightmost node. But in Binary Tree, we must visit every node to figure out maximum. So the idea
is to traverse the given tree and for every node return maximum of 3 values.

1. Node’s data.
2. Maximum in node’s left subtree.
3. Maximum in node’s right subtree.
Below is the implementation of above approach.

C++Java
// C++ program to find maximum and
// minimum in a Binary Tree
#include <bits/stdc++.h>
#include <iostream>
using namespace std;

// A tree node
class Node {
public:
int data;
Node *left, *right;
/* Constructor that allocates a new
node with the given data and NULL
left and right pointers. */
Node(int data)
{
this->data = data;
this->left = NULL;
this->right = NULL;
}
};

// Returns maximum value in a given


// Binary Tree
int findMax(Node* root)
{
// Base case
if (root == NULL)
return INT_MIN;

// Return maximum of 3 values:


// 1) Root's data 2) Max in Left Subtree
// 3) Max in right subtree
int res = root->data;
int lres = findMax(root->left);
int rres = findMax(root->right);
if (lres > res)
res = lres;
if (rres > res)
res = rres;
return res;
}

// Driver Code
int main()
{
Node* NewRoot = NULL;
Node* root = new Node(2);
root->left = new Node(7);
root->right = new Node(5);
root->left->right = new Node(6);
root->left->right->left = new Node(1);
root->left->right->right = new Node(11);
root->right->right = new Node(9);
root->right->right->left = new Node(4);

// Function call
cout << "Maximum element is " << findMax(root) << endl;
return 0;
}

// This code is contributed by


// rathbhupendra

Output

Maximum element is 11
Complexity Analysis:

Time Complexity: O(N).


In the recursive function calls, every node of the tree is processed once and hence the complexity
due to the function is O(N) if there are total N nodes in the tree. Therefore, the time complexity
is O(N).

Space Complexity: O(N).


Recursive call is happening. The every node is processed once and considering the stack space,
the space complexity will be O(N).
Mark as Read
Report An IssueIf you are facing

Delete a node from BST

Given a Binary Search Tree and a node value x. Delete the node with the given value
x from the BST. If no node with value x exists, then do not make any change. Return
the root of the BST after deleting the node with value x. Do not make any update if
there's no node with value x present in the BST.

Note: The generated output will be the inorder traversal of the modified tree.

Examples :

Input:
2
/ \
1 3
x = 12
Output: 1 2 3
Explanation: In the given input there is no node with
value 12 , so the tree will remain same.
Input:
1
\
2
\
8
/ \
5 11
/ \ / \
4 7 9 12
x = 9
Output: 1 2 4 5 7 8 11 12
Explanation: In the given input tree after deleting 9
will be
1
\
2
\
8
/ \
5 11
/ \ \
4 7 12
Expected Time Complexity: O(Height of the BST).
Expected Auxiliary Space: O(Height of the BST).
Node * minValueNode(Node* node)

Node* current = node;

/* loop down to find the leftmost leaf */

while (current->left != NULL)

current = current->left;

return current;

// Function to delete a node from BST.

Node *deleteNode(Node *root, int key) {

// base case

if (root == NULL) return root;

// If the key to be deleted is smaller than the root's key,

// then it lies in left subtree

if (key < root->data)

root->left = deleteNode(root->left, key);


// If the key to be deleted is greater than the root's key,

// then it lies in right subtree

else if (key > root->data)

root->right = deleteNode(root->right, key);

// if key is same as root's key, then This is the node

// to be deleted

else

// node with only one child or no child

if (root->left == NULL)

Node *temp = root->right;

free(root);

return temp;

else if (root->right == NULL)

Node *temp = root->left;

free(root);

return temp;

}
// node with two children: Get the inorder successor (smallest

// in the right subtree)

Node* temp = minValueNode(root->right);

// Copy the inorder successor's content to this node

root->data = temp->data;

// Delete the inorder successor

root->right = deleteNode(root->right, temp->data);

return root;

Diameter of a Binary Tree

Description - The diameter of a tree (sometimes called the width) is the number of nodes on the
longest path between two end nodes. The diagram below shows two trees each with diameter
nine, the leaves that form the ends of a longest path are shaded (note that there is more than one
path in each tree of length nine, but no path longer than nine nodes).
Solution - The diameter of a tree T is the largest of the following quantities:

1. the diameter of T’s left subtree


2. the diameter of T’s right subtree
3. the longest path between leaves that goes through the root of T (this can be computed
from the heights of the subtrees of T)

Pseudo Code

int diameter(struct node *root, int* height)


{

int lh = 0, rh = 0
int ldiameter = 0, rdiameter = 0

if(root == NULL)
{
*height = 0
return 0 /* diameter is also 0 */
}
ldiameter = diameter(root->left, &lh)
rdiameter = diameter(root->right, &rh)

/* Height of current node is max of heights of left and


right subtrees plus 1*/
*height = max(lh, rh) + 1

return max(lh + rh + 1, max(ldiameter, rdiameter))


}

Size of Binary Tree

Size of a tree is the number of elements present in the tree. Size of the below tree is 5.

Size() function recursively calculates the size of a tree. It works as follows:


Size of a tree = Size of left subtree + 1 + Size of right subtree.

Algorithm:

size(tree)
1. If tree is empty then return 0
2. Else
(a) Get the size of left subtree recursively i.e., call
size( tree->left-subtree)
(a) Get the size of right subtree recursively i.e., call
size( tree->right-subtree)
(c) Calculate size of the tree as following:
tree_size = size(left-subtree) + size(right-
subtree) + 1
(d) Return tree_size

C++Java
// A recursive C++ program to
// calculate the size of the tree
#include <bits/stdc++.h>
using namespace std;

/* A binary tree node has data, pointer to left child


and a pointer to right child */
class node
{
public:
int data;
node* left;
node* right;
};

/* Helper function that allocates a new node with the


given data and NULL left and right pointers. */
node* newNode(int data)
{
node* Node = new node();
Node->data = data;
Node->left = NULL;
Node->right = NULL;

return(Node);
}

/* Computes the number of nodes in a tree. */


int size(node* node)
{
if (node == NULL)
return 0;
else
return(size(node->left) + 1 + size(node->right));
}

/* Driver code*/
int main()
{
node *root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);

cout << "Size of the tree is " << size(root);


return 0;
}

Output:

Size of the tree is 5


Time Complexity: O(N)

As every node is visited once.

Auxiliary Space: O(N)

The extra space is due to the recursion call stack and the worst case occurs when the tree is either
left skewed or right skewed.

Since this program is similar to traversal of tree, time and space complexities will be same as
Tree traversal

Check for Balanced Binary Tree

A height balanced binary tree is a binary tree in which the height of the left subtree and
right subtree of any node does not differ by more than 1 and both the left and right
subtree are also height balanced.

In this article, we will look into methods how to determine if given Binary trees are height-
balanced
Examples: The tree on the left is a height balanced binary tree. Whereas the tree on the
right is not a height balanced tree. Because the left subtree of the root has a height which
is 2 more than the height of the right subtree.

Naive Approach: To check if a tree is height-balanced:

Get the height of left and right subtrees using dfs traversal. Return true if the difference
between heights is not more than 1 and left and right subtrees are balanced, otherwise
return false.

Below is the implementation of the above approach.

C++Java
/* CPP program to check if
a tree is height-balanced or not */

#include <bits/stdc++.h>
using namespace std;

/* A binary tree node has data,


pointer to left child and
a pointer to right child */
class Node {
public:
int data;
Node* left;
Node* right;
Node(int d)
{
int data = d;
left = right = NULL;
}
};

// Function to calculate the height of a tree


int height(Node* node)
{
// base case tree is empty
if (node == NULL)
return 0;

// If tree is not empty then


// height = 1 + max of left height
// and right heights
return 1 + max(height(node->left), height(node->right));
}

// Returns true if binary tree


// with root as root is height-balanced
bool isBalanced(Node* root)
{
// for height of left subtree
int lh;

// for height of right subtree


int rh;

// If tree is empty then return true


if (root == NULL)
return 1;

// Get the height of left and right sub trees


lh = height(root->left);
rh = height(root->right);

if (abs(lh - rh) <= 1 && isBalanced(root->left)


&& isBalanced(root->right))
return 1;

// If we reach here then tree is not height-balanced


return 0;
}

// Driver code
int main()
{
Node* root = new Node(1);
root->left = new Node(2);
root->right = new Node(3);
root->left->left = new Node(4);
root->left->right = new Node(5);
root->left->left->left = new Node(8);

if (isBalanced(root))
cout << "Tree is balanced";
else
cout << "Tree is not balanced";
return 0;
}

Output
Tree is not balanced
Time Complexity: O(n^2) in case of full binary tree.
Auxiliary Space: O(n) space for call stack since using recursion

Efficient implementation: Above implementation can be optimized by

Calculating the height in the same recursion rather than calling a height() function
separately.
 For each node make two recursion calls – one for left subtree and the other for the right
subtree.
 Based on the heights returned from the recursion calls, decide if the subtree whose root is
the current node is height-balanced or not.
 If it is balanced then return the height of that subtree. Otherwise, return -1 to denote that
the subtree is not height-balanced.
Below is the implementation of the above approach.

C++Java
// C++ code to implement the approach

#include <bits/stdc++.h>
using namespace std;

// Structure of a tree node


struct Node {
int key;
struct Node* left;
struct Node* right;
Node(int k)
{
key = k;
left = right = NULL;
}
};

// Function to check if tree is height balanced


int isBalanced(Node* root)
{
if (root == NULL)
return 0;
int lh = isBalanced(root->left);
if (lh == -1)
return -1;
int rh = isBalanced(root->right);
if (rh == -1)
return -1;

if (abs(lh - rh) > 1)


return -1;
else
return max(lh, rh) + 1;
}

// Driver code
int main()
{
Node* root = new Node(10);
root->left = new Node(5);
root->right = new Node(30);
root->right->left = new Node(15);
root->right->right = new Node(20);

if (isBalanced(root) > 0)
cout << "Balanced";
else
cout << "Not Balanced";
return 0;
}

Output
Balanced
Time Complexity: O(n)
 Because we are only one dfs call and utilizing the height returned from that to determine
the height balance, it is performing the task in linear time.
Auxiliary Space: O(n)

Diameter of a Binary Tree

The diameter of a tree (sometimes called the width) is the number of nodes on the longest path
between two end nodes. The diagram below shows two trees each with diameter nine, the leaves
that form the ends of a longest path are shaded (note that there is more than one path in each tree
of length nine, but no path longer than nine nodes).

Solution: The diameter of a tree T is the largest of the following quantities:

 The diameter of T's left subtree.


 The diameter of T's right subtree.
 The longest path between leaves that goes through the root of T (this can be computed
from the heights of the subtrees of T).
The longest path between leaves that goes through a particular node say,
nd

can be calculated as:

1 + height of left subtree of nd + height of right subtree of nd

Therefore, final Diameter of a node can be calculated as:

Diameter = maximum(lDiameter, rDiameter, 1 + lHeight + rHeight)

Where,
lDiameter = Diameter of left subtree
rDiameter = Diameter of right subtree
lHeight = Height of left subtree
rHeight = Height of right subtree

Implementation :

C++Java
// C++ program to calculate Diameter of a Binary Tree

#include <bits/stdc++.h>
using namespace std;

// Binary Tree Node


struct node
{
int data;
struct node* left, *right;
};

// Function to create a new node of tree


// and returns pointer
struct node* newNode(int data);

// Function to Compute height of a tree


int height(struct node* node);
// Function to get diameter of a binary tree
int diameter(struct node * tree)
{
/* base case where tree is empty */
if (tree == NULL)
return 0;

/* get the height of left and right sub-trees */


int lheight = height(tree->left);
int rheight = height(tree->right);

/* get the diameter of left and right sub-trees */


int ldiameter = diameter(tree->left);
int rdiameter = diameter(tree->right);

/* Return max of following three


1) Diameter of left subtree
2) Diameter of right subtree
3) Height of left subtree + height of right subtree + 1 */
return max(lheight + rheight + 1, max(ldiameter, rdiameter));
}

/* UTILITY FUNCTIONS TO TEST diameter() FUNCTION */

/* The function Compute the "height" of a tree. Height is the


number f nodes along the longest path from the root node
down to the farthest leaf node.*/
int height(struct node* node)
{
/* base case tree is empty */
if(node == NULL)
return 0;

/* If tree is not empty then height = 1 + max of left


height and right heights */
return 1 + max(height(node->left), height(node->right));
}

/* Helper function that allocates a new node with the


given data and NULL left and right pointers. */
struct node* newNode(int data)
{
struct node* node = (struct node*)
malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return(node);
}

// Driver Code
int main()
{

/* Constructed binary tree is


1
/ \
2 3
/ \
4 5
*/
struct node *root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);

cout<<"Diameter of the given binary tree is "<<diameter(root);

return 0;
}’

Output:

Diameter of the given binary tree is 4


Time Complexity: O(N2), where N is the number of nodes in the binary tree.

Auxiliary Space: O(N) for call stack

Efficient Approach: To solve the problem follow the below idea:

The above implementation can be optimized by calculating the height in the same
recursion rather than calling a height() separately.

Below is the implementation of the above approach:

C++JavaPython3C#Javascript
// Recursive optimized C++ program to find the diameter of a
// Binary Tree
#include <bits/stdc++.h>
using namespace std;

// A binary tree node has data, pointer to left child


// and a pointer to right child
struct node {
int data;
struct node *left, *right;
};

// function to create a new node of tree and returns pointer


struct node* newNode(int data);

int diameterOpt(struct node* root, int* height)


{
// lh --> Height of left subtree
// rh --> Height of right subtree
int lh = 0, rh = 0;

// ldiameter --> diameter of left subtree


// rdiameter --> Diameter of right subtree
int ldiameter = 0, rdiameter = 0;

if (root == NULL) {
*height = 0;
return 0; // diameter is also 0
}

// Get the heights of left and right subtrees in lh and


// rh And store the returned values in ldiameter and
// ldiameter
ldiameter = diameterOpt(root->left, &lh);
rdiameter = diameterOpt(root->right, &rh);

// Height of current node is max of heights of left and


// right subtrees plus 1
*height = max(lh, rh) + 1;

return max(lh + rh + 1, max(ldiameter, rdiameter));


}

// Helper function that allocates a new node with the


// given data and NULL left and right pointers.
struct node* newNode(int data)
{
struct node* node
= (struct node*)malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return (node);
}

// Driver Code
int main()
{

/* Constructed binary tree is


1
/ \
2 3
/ \
4 5
*/
struct node* root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);

int height = 0;

// Function Call
cout << "Diameter of the given binary tree is "
<< diameterOpt(root, &height);

return 0;
}

// This code is contributed by probinsah.

Output

Diameter of the given binary tree is 4


Time Complexity: O(N)
Auxiliary Space: O(N) due to recursive calls.
Check for BST

A binary search tree (BST) is a node based binary tree data structure which has the
following properties.

 The left subtree of a node contains only nodes with keys less than the node's key.
 The right subtree of a node contains only nodes with keys greater than the
node's key.
 Both the left and right subtrees must also be binary search trees.
From the above properties it naturally follows that:

 Each node (item in the tree) has a distinct key.

METHOD 1 (Simple but Wrong)


Following is a simple program. For each node, check if the left node of it is smaller than
the node and right node of it is greater than the node.

C++Java
int isBST(struct node* node)
{
if (node == NULL)
return 1;

/* false if left is > than node */


if (node->left != NULL && node->left->data > node->data)
return 0;

/* false if right is < than node */


if (node->right != NULL && node->right->data < node->data)
return 0;

/* false if, recursively, the left or right is not a BST */


if (!isBST(node->left) || !isBST(node->right))
return 0;

/* passing all that, it's a BST */


return 1;
}

// This code is contributed by shubhamsingh10

This approach is wrong as this will return true for below binary tree (and below
tree is not a BST because 4 is in left subtree of 3)

METHOD 2 (Correct but not efficient)


For each node, check if max value in left subtree is smaller than the node and min value
in right subtree greater than the node.

C++Java
/* Returns true if a binary tree is a binary search tree */
int isBST(struct node* node)
{
if (node == NULL)
return 1;

/* false if the max of the left is > than us */


if (node->left != NULL && maxValue(node->left) >= node->data)
return 0;

/* false if the min of the right is <= than us */


if (node->right != NULL && minValue(node->right) <= node->data)
return 0;

/* false if, recursively, the left or right is not a BST */


if (!isBST(node->left) || !isBST(node->right))
return 0;

/* passing all that, it's a BST */


return 1;
}

// This code is contributed by shubhamsingh10

It is assumed that you have helper functions minValue() and maxValue() that return the
min or max int value from a non-empty tree

METHOD 3 (Correct and Efficient):


Method 2 above runs slowly since it traverses over some parts of the tree many times. A
better solution looks at each node only once. The trick is to write a utility helper function
isBSTUtil(struct node* node, int min, int max) that traverses down the tree keeping track
of the narrowing min and max allowed values as it goes, looking at each node only
once. The initial values for min and max should be INT_MIN and INT_MAX -- they
narrow from there.

Note: This method is not applicable if there are duplicate elements with value INT_MIN
or INT_MAX.

Below is the implementation of the above approach:

C++Java
#include<bits/stdc++.h>

using namespace std;

/* A binary tree node has data,


pointer to left child and
a pointer to right child */
class node
{
public:
int data;
node* left;
node* right;

/* Constructor that allocates


a new node with the given data
and NULL left and right pointers. */
node(int data)
{
this->data = data;
this->left = NULL;
this->right = NULL;
}
};
int isBSTUtil(node* node, int min, int max);

/* Returns true if the given


tree is a binary search tree
(efficient version). */
int isBST(node* node)
{
return(isBSTUtil(node, INT_MIN, INT_MAX));
}

/* Returns true if the given


tree is a BST and its values
are >= min and <= max. */
int isBSTUtil(node* node, int min, int max)
{
/* an empty tree is BST */
if (node==NULL)
return 1;

/* false if this node violates


the min/max constraint */
if (node->data < min || node->data > max)
return 0;

/* otherwise check the subtrees recursively,


tightening the min or max constraint */
return
isBSTUtil(node->left, min, node->data-1) && // Allow only distinct
values
isBSTUtil(node->right, node->data+1, max); // Allow only distinct
values
}

/* Driver code*/
int main()
{
node *root = new node(4);
root->left = new node(2);
root->right = new node(5);
root->left->left = new node(1);
root->left->right = new node(3);

if(isBST(root))
cout<<"Is BST";
else
cout<<"Not a BST";
return 0;
}

// This code is contributed by rathbhupendra

Output:

IS BST
Time Complexity: O(n)
Auxiliary Space: O(1) if Function Call Stack size is not considered, otherwise O(n)

Simplified Method 3
We can simplify method 2 using NULL pointers instead of INT_MIN and INT_MAX
values.

C++Java
// C++ program to check if a given tree is BST.
#include <bits/stdc++.h>
using namespace std;

/* A binary tree node has data, pointer to


left child and a pointer to right child */
struct Node
{
int data;
struct Node* left, *right;
};

// Returns true if given tree is BST.


bool isBST(Node* root, Node* l=NULL, Node* r=NULL)
{
// Base condition
if (root == NULL)
return true;

// if left node exist then check it has


// correct data or not i.e. left node's data
// should be less than root's data
if (l != NULL and root->data <= l->data)
return false;

// if right node exist then check it has


// correct data or not i.e. right node's data
// should be greater than root's data
if (r != NULL and root->data >= r->data)
return false;

// check recursively for every node.


return isBST(root->left, l, root) and
isBST(root->right, root, r);
}

/* Helper function that allocates a new node with the


given data and NULL left and right pointers. */
struct Node* newNode(int data)
{
struct Node* node = new Node;
node->data = data;
node->left = node->right = NULL;
return (node);
}

/* Driver program to test above functions*/


int main()
{
struct Node *root = newNode(3);
root->left = newNode(2);
root->right = newNode(5);
root->left->left = newNode(1);
root->left->right = newNode(4);

if (isBST(root,NULL,NULL))
cout << "Is BST";
else
cout << "Not a BST";

return 0;
}

Output:

Not a BST
METHOD 4(Using In-Order Traversal)
Thanks to LJW489 for suggesting this method.
1) Do In-Order Traversal of the given tree and store the result in a temp array.
2) This method assumes that there are no duplicate values in the tree
3) Check if the temp array is sorted in ascending order, if it is, then the tree is BST.
Time Complexity: O(n)
We can avoid the use of a Auxiliary Array. While doing In-Order traversal, we can keep
track of previously visited node. If the value of the currently visited node is less than the
previous value, then tree is not BST. Thanks to ygos for this space optimization.

C++Java
bool isBST(node* root)
{
static node *prev = NULL;

// traverse the tree in inorder fashion


// and keep track of prev node
if (root)
{
if (!isBST(root->left))
return false;

// Allows only distinct valued nodes


if (prev != NULL &&
root->data <= prev->data)
return false;

prev = root;

return isBST(root->right);
}

return true;
}

// This code is contributed by rathbhupendra

The use of a static variable can also be avoided by using a reference to the prev node as
a parameter.

C++Java
// C++ program to check if a given tree is BST.
#include <bits/stdc++.h>
using namespace std;

/* A binary tree node has data, pointer to


left child and a pointer to right child */
struct Node
{
int data;
struct Node* left, *right;
Node(int data)
{
this->data = data;
left = right = NULL;
}
};

bool isBSTUtil(struct Node* root, Node *&prev)


{
// traverse the tree in inorder fashion and
// keep track of prev node
if (root)
{
if (!isBSTUtil(root->left, prev))
return false;

// Allows only distinct valued nodes


if (prev != NULL && root->data <= prev->data)
return false;

prev = root;

return isBSTUtil(root->right, prev);


}

return true;
}

bool isBST(Node *root)


{
Node *prev = NULL;
return isBSTUtil(root, prev);
}

/* Driver program to test above functions*/


int main()
{
struct Node *root = new Node(3);
root->left = new Node(2);
root->right = new Node(5);
root->left->left = new Node(1);
root->left->right = new Node(4);

if (isBST(root))
cout << "Is BST";
else
cout << "Not a BST";
return 0;
}

Output:

Not a BST

Finding LCA in Binary Tree

Given a Binary Tree and the value of two nodes n1 and n2. The task is to find the lowest
common ancestor of the nodes n1 and n2 in the given Binary Tree.

The LCA or Lowest Common Ancestor of any two nodes N1 and N2 is defined as the
common ancestor of both the nodes which is closest to them. That is the distance of the
common ancestor from the nodes N1 and N2 should be least possible.

Below image represents a tree and LCA of different pair of nodes (N1, N2) in it:

Finding LCA
Method 1: The simplest method of finding LCA of two nodes in a Binary Tree is to observe that
the LCA of the given nodes will be the last common node in the paths from the root node to the
given nodes.

For Example: consider the above-given tree and nodes 4 and 5.

 Path from root to node 4: [1, 2, 4]


 Path from root to node 5: [1, 2, 5].

The last common node is 2 which will be the LCA.

Algorithm:

1. Find the path from the root node to node n1 and store it in a vector or array.
2. Find the path from the root node to node n2 and store it in another vector or array.
3. Traverse both paths untill the values in arrays are same. Return the common element just
before the mismatch.

Implementation:

C++Java
// C++ Program for Lowest Common Ancestor
// in a Binary Tree

#include <iostream>
#include <vector>

using namespace std;

// A Binary Tree node


struct Node {
int key;
struct Node *left, *right;
};

// Utility function creates a new binary tree


// node with given key
Node* newNode(int k)
{
Node* temp = new Node;
temp->key = k;
temp->left = temp->right = NULL;
return temp;
}

// Function to find the path from root node to


// given root of the tree, Stores the path in a
// vector path[], returns true if path exists
// otherwise false
bool findPath(Node* root, vector<int>& path, int k)
{
// base case
if (root == NULL)
return false;

// Store this node in path vector.


// The node will be removed if
// not in path from root to k
path.push_back(root->key);

// See if the k is same as root's key


if (root->key == k)
return true;

// Check if k is found in left or right sub-tree


if ((root->left && findPath(root->left, path, k)) ||
(root->right && findPath(root->right, path, k)))
return true;

// If not present in subtree rooted with root,


// remove root from path[] and return false
path.pop_back();

return false;
}

// Function to return LCA if node n1, n2 are


// present in the given binary tree, otherwise
// return -1
int findLCA(Node* root, int n1, int n2)
{
// to store paths to n1 and n2 from the root
vector<int> path1, path2;

// Find paths from root to n1 and root to n1.


// If either n1 or n2 is not present, return -1
if (!findPath(root, path1, n1) || !findPath(root, path2, n2))
return -1;

// Compare the paths to get the first


// different value
int i;

for (i = 0; i < path1.size() && i < path2.size(); i++)


if (path1[i] != path2[i])
break;
return path1[i - 1];
}

// Driver Code
int main()
{
// Let us create the Binary Tree
// as shown in the above diagram
Node* root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
root->right->left = newNode(6);
root->right->right = newNode(7);

cout << "LCA(4, 5) = " << findLCA(root, 4, 5);


cout << "\nLCA(4, 6) = " << findLCA(root, 4, 6);
cout << "\nLCA(3, 4) = " << findLCA(root, 3, 4);
cout << "\nLCA(2, 4) = " << findLCA(root, 2, 4);

return 0;
}

Output:

LCA(4, 5) = 2
LCA(4, 6) = 1
LCA(3, 4) = 1
LCA(2, 4) = 2

Analysis: The time complexity of the above solution is O(N) where N is the number of nodes in
the given Tree and the above solution also takes O(N) extra space.

Method 2: The method 1 finds LCA in O(N) time but requires three tree traversals plus extra
spaces for path arrays. If we assume that the keys are present in Binary Tree, we can find LCA
using single traversal of Binary Tree and without extra storage for path arrays.

The idea is to traverse the tree starting from the root node. If any of the given keys (n1 and n2)
matches with root, then root is LCA (assuming that both keys are present). If root doesn't match
with any of the keys, we recur for left and right subtrees. The node which has one key present in
its left subtree and the other key present in the right subtree is the LCA. If both keys lie in left
subtree, then left subtree has LCA also, otherwise, LCA lies in the right subtree.

Below is the implementation of the above approach:

C++Java
// C++ Program to find LCA of n1 and n2 using
// one traversal of Binary Tree

#include <iostream>

using namespace std;

// A Binary Tree Node


struct Node {
struct Node *left, *right;
int key;
};

// Utility function to create a new tree Node


Node* newNode(int key)
{
Node* temp = new Node;
temp->key = key;
temp->left = temp->right = NULL;
return temp;
}

// This function returns pointer to LCA of two given


// values n1 and n2. This function assumes that
// n1 and n2 are present in Binary Tree
struct Node* findLCA(struct Node* root, int n1, int n2)
{
// Base case
if (root == NULL)
return NULL;

// If either n1 or n2 matches with root's key, report


// the presence by returning root (Note that if a key is
// ancestor of other, then the ancestor key becomes LCA
if (root->key == n1 || root->key == n2)
return root;

// Look for keys in left and right subtrees


Node* left_lca = findLCA(root->left, n1, n2);
Node* right_lca = findLCA(root->right, n1, n2);

// If both of the above calls return Non-NULL,


// then one key is present in once subtree and
// other is present in other,
// So this node is the LCA
if (left_lca && right_lca)
return root;

// Otherwise check if left subtree or


// right subtree is LCA
return (left_lca != NULL) ? left_lca : right_lca;
}

// Driver Code
int main()
{
// Let us create binary tree given in the above example
Node* root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
root->right->left = newNode(6);
root->right->right = newNode(7);

cout << "LCA(4, 5) = " << findLCA(root, 4, 5)->key;


cout << "nLCA(4, 6) = " << findLCA(root, 4, 6)->key;
cout << "nLCA(3, 4) = " << findLCA(root, 3, 4)->key;
cout << "nLCA(2, 4) = " << findLCA(root, 2, 4)->key;

return 0;
}

Output:

LCA(4, 5) = 2nLCA(4, 6) = 1nLCA(3, 4) = 1nLCA(2, 4) = 2


Problem #3 : Convert a Binary Tree into its Mirror Tree

Description - Mirror of a Binary Tree T is another Binary Tree M(T) with left and right children
of all non-leaf nodes interchanged. Trees in the below figure are mirror of each other.

Solution - The idea is to recursively call for left and right subtrees of a given node. On each
recursive call swap the pointers of the children nodes.
Pseudo Code

// function to convert binary tree to it's mirror


void mirror(struct Node* node)
{
if (node == NULL)
return
else
{
struct Node* temp
/* Recur for subtrees */
mirror(node->left)
mirror(node->right)

/* swap the pointers in this node */


temp = node->left
node->left = node->right
node->right = temp
}
}

Left, Right, Top and Bottom View of a Binary Tree

the Problem: Given a Binary Tree. The task is to print the nodes of the binary tree when viewed
from different sides. That is, the left view of the binary tree will contain only those nodes that
can be seen when the Binary tree is viewed from the left.

Example:

Consider the Below Binary Tree:

Left View of above Tree will be: 1, 2, 4


Right View of above Tree will be: 1, 3, 7
Top View of above Tree will be: 4, 2, 1, 3, 7
Bottom View of above Tree will be: 4, 2, 6, 3, 7

Let us now look at each of the solutions in details:

 Left View: A simple solution is to notice that the nodes appearing in the left view of the
binary tree are the first nodes at every level. So, the idea is to do a level order traversal of
the binary tree using a marker to identify levels and print the first node at every level.
Below is the complete function to print left view:
CPP
// Function to print the left view of the binary tree
void leftViewUtil(Node root)
{
// Declare a queue for Level order Traversal
queue<Node*> q;

if (root == NULL)
return;

// Push root
q.push(root);

// Delimiter
q.push(NULL);

while (!q.empty()) {
Node* temp = q.front();

if (temp) {

// Prints first node


// of each level
print temp->data;

// Push children of all nodes at


// current level
while (q.front() != NULL) {

// If left child is present


// push into queue
if (temp->left)
q.push(temp->left);

// If right child is present


// push into queue
if (temp->right)
q.push(temp->right);

// Pop the current node


q.pop();

temp = q.front();
}

// Push delimiter
// for the next level
q.push(NULL);
}

// Pop the delimiter of


// the previous level
q.pop();
}
}

 Right View: Printing Right View of the Binary Tree is similar to the above approach of
printing the Left view of the tree. The idea is to print the last node present at every level.
So, perform a level order traversal using a delimeter to identify levels and print the last
node present at every level.
 Top View: Top view of a binary tree is the set of nodes visible when the tree is viewed
from the top. A node x is there in output if x is the topmost node at its horizontal
distance. Horizontal distance of left child of a node x is equal to the horizontal distance of
x minus 1, and that of right child is the horizontal distance of x plus 1. So, the idea is to
do a level order traversal of the tree and calculate the horizontal distance of every node
from the root node and print those nodes which are the first nodes of a particular
horizontal distance. Hashing can be used to keep a check on whether any node with a
particular horizontal distance is encountered yet or not. Below is the function
implementing the above approach:
CPP
// Structure of binary tree
// Binary Tree node is modified to contain
// an extra parameter hd, which is the
// horizontal distance of the node from root node.
struct Node
{
Node * left;
Node* right;
int hd;
int data;
};

// Function to print the topView of


// the binary tree
void topview(Node* root)
{
if(root==NULL)
return;

queue<Node*>q;

map<int,int> m;

int hd=0;

root->hd = hd;

// push node and horizontal distance to queue


q.push(root);

print "The top view of the tree is : ";


while(q.size())
{
hd = root->hd;

// Check if any node with this horizontal distance


// is encontered yet or not.
// If not insert, current node's data to Map
if(m.count(hd)==0)
m[hd]=root->data;

// Push the left child with its


// horizontal distance to queue
if(root->left)
{
root->left->hd=hd-1;
q.push(root->left);
}

// Push the right child with its


// horizontal distance to queue
if(root->right)
{
root->right->hd=hd+1;
q.push(root->right);
}

q.pop();
root=q.front();
}

// Print the map as it stores the nodes


// appearing in the Top View
for(auto i=m.begin();i!=m.end();i++)
{
cout<<i->second<<" ";
}
}

 Bottom View: The Bottom View of a binary tree can be printed using the similar
approach as that of printing the Top View. A node x is there in output if x is the bottom
most instead of the top most node at its horizontal distance. The process of printing the
bottom view is almost the same as that of top view with a little modification that while
storing the node's data along with a particular horizontal distance in the map, keep
updating the node's data in the map for a particular horizontal distance so that the map
contains the last node appearing with a particular horizontal distance instead of first.
Construct Binary Tree from Inorder and Preorder

Let us consider the below traversals:

 Inorder sequence: D B E A F C
 Preorder sequence: A B D E C F
subtree and elements on right in the right subtree. So we know the below structure now.

A
/ \
/ \
D B E F C
We recursively follow the above steps and get the following tree.

A
/ \
/ \
B C
/ \ /
/ \ /
D E F
Algorithm:

1. Pick an element from Preorder. Increment a Preorder Index Variable (preIndex in below
code) to pick the next element in the next recursive call.
2. Create a new tree node tNode with the data as the picked element.
3. Find the picked element’s index in Inorder. Let the index be inIndex.
4. Call buildTree for elements before inIndex and make the built tree as a left subtree of
tNode.
5. Call buildTree for elements after inIndex and make the built tree as a right subtree of
tNode.
6. return tNode.
We store indexes of inorder traversal in a hash table. So that search can be done O(1) time.

C++Java
/* C++ program to construct tree using inorder
and preorder traversals */
#include <bits/stdc++.h>
using namespace std;

/* A binary tree node has data, pointer to left child


and a pointer to right child */
struct Node {
char data;
struct Node* left;
struct Node* right;
};

struct Node* newNode(char data)


{
struct Node* node = new Node;
node->data = data;
node->left = node->right = NULL;
return (node);
}

/* Recursive function to construct binary of size


len from Inorder traversal in[] and Preorder traversal
pre[]. Initial values of inStrt and inEnd should be
0 and len -1. The function doesn't do any error
checking for cases where inorder and preorder
do not form a tree */
struct Node* buildTree(char in[], char pre[], int inStrt,
int inEnd, unordered_map<char, int>&
mp)
{
static int preIndex = 0;

if (inStrt > inEnd)


return NULL;

/* Pick current node from Preorder traversal using preIndex


and increment preIndex */
char curr = pre[preIndex++];
struct Node* tNode = newNode(curr);

/* If this node has no children then return */


if (inStrt == inEnd)
return tNode;

/* Else find the index of this node in Inorder traversal */


int inIndex = mp[curr];

/* Using index in Inorder traversal, construct left and


right subtress */
tNode->left = buildTree(in, pre, inStrt, inIndex - 1, mp);
tNode->right = buildTree(in, pre, inIndex + 1, inEnd, mp);

return tNode;
}

// This function mainly creates an unordered_map, then


// calls buildTree()
struct Node* buldTreeWrap(char in[], char pre[], int len)
{
// Store indexes of all items so that we
// we can quickly find later
unordered_map<char, int> mp;
for (int i = 0; i < len; i++)
mp[in[i]] = i;

return buildTree(in, pre, 0, len - 1, mp);


}

/* This function is here just to test buildTree() */


void printInorder(struct Node* node)
{
if (node == NULL)
return;
printInorder(node->left);
printf("%c ", node->data);
printInorder(node->right);
}

/* Driver program to test above functions */


int main()
{
char in[] = { 'D', 'B', 'E', 'A', 'F', 'C' };
char pre[] = { 'A', 'B', 'D', 'E', 'C', 'F' };
int len = sizeof(in) / sizeof(in[0]);

struct Node* root = buldTreeWrap(in, pre, len);

/* Let us test the built tree by printing


Inorder traversal */
printf("Inorder traversal of the constructed tree is \n");
printInorder(root);
}

Output

Inorder traversal of the constructed tree is


D B E A F C
Time Complexity: O(n)
Auxiliary Space: O(n), The extra space is used to store the elements in the map also due to
recursive function call stack.
Mark as Read
Report An IssueIf you

You might also like