Calculate Height of a Binary Tree Recursive method - binary-tree

I want to know if this implementation is correct for finding height of BT. Please give me your thoughts on it.
public class Node {
int value;
Node left = null;
Node right = null;
public Node(int value) {
this.value = value;
}
}
class Main {
public int BTHeight(Node root) {
//tree is empty.
if(root == null) {
return -1;
}
//recur for left and right tree.
else if(root.left != null || root.right != null) {
return 1 + Math.max(BTHeight(root.left) + BTHeight(root.right));
}
//tree has only one node. that node is both the root and the leaf
return 0;
}
}

No, it is not a correct implementation as your code has a compilation error here (Math.max function need two input parameters):
return 1 + Math.max(BTHeight(root.left) + BTHeight(root.right));
The definition of height as stated in the book Introduction to Algorithms, 3rd Edition (Cormen, page 1177), is:
The height of a node in a tree is the number of edges on the longest simple downward path from the node to a leaf, and the height of a tree is the height of its root. The height of a tree is also equal to the largest depth of any node in the tree.
A NULL node it is not a tree (by definition) so there are several values of height to choose as default like undefined or -1 or 0, it depend on the purpose. The implementation of height's definition stated above is usually shorter if used -1 as height of a NULL node.
It would be like this:
public int BTHeight(Node root) {
return root == null ? -1 : Math.max(BTHeight(root.left)+1, BTHeight(root.right)+1);}
Corner case examples:
Height of a NULL node: -1
Height of a leaf node: 0
You can use also an alternative definition:
The height of a node in a tree is the number of nodes on the longest simple downward path from the node to a leaf.
In this case it would be better to use 0 as height of a NULL node as a leaf's height is 1.
public int BTHeight(Node root) {
return root == null ? 0 : Math.max(BTHeight(root.left)+1, BTHeight(root.right)+1);}
Corner case examples:
Height of a NULL node: 0
Height of a leaf node: 1
You can see that both codes are basically the same and that is convenient in case you have to change from one definition to another.

Related

What does minus 1 means in the method about calculating height of red-black tree?

I cannot understand why we should minus 1 in line 4.
I think just returning height(root) is fine, what does minus 1 mean?
public int height() {
if(root == null)
return 0;
return height(root) - 1;
}
public int height(Node<K,V> node) {
if (node == null)
return 0;
int leftheight = height(node.left) + 1
int rightheight = height(node.right) + 1
if (leftheight > rightheight)
return leftheight;
return rightheight;
}
This minus one is necessary because the second height function does not calculate the height, but one more than the height.
The height of a tree is defined as the number of edges on the longest path from the root to a leaf, but the second function calculates the number of nodes (or levels) on the longest path from the root to a leaf, which is always one more.
I agree that this is a strange way of doing it, as actually it makes the name of the second function wrong: it doesn't do what it says.
Moreover, the main function has a problem too, because when the root is null, the height should return -1.
It is more natural to change the base case, and make the second function really return the height of the node that is passed as argument:
public int height() {
return height(root); // Simple: if no argument was passed, the default is the root
}
public int height(Node<K,V> node) {
if (node == null)
return -1; // <-----
int leftheight = height(node.left) + 1
int rightheight = height(node.right) + 1
if (leftheight > rightheight)
return leftheight;
return rightheight;
}
It may be strange to have the value -1 there, but the reasoning is as follows:
This is a tree with height 1:
a
/ \
b c
... because the longest path from the root has one edge; it is a tree with 2 levels, and the height is one less than the number of levels.
This is a tree with height 0:
a
Here the number of levels is 1, and so the height is 0.
One step more, is an empty tree -- it doesn't even have a node, and zero levels, and so the corresponding height should be -1.
See also What is the definition for the height of a tree?.

How to calculate a height of a tree

I am trying to learn DSA and got stuck on one problem.
How to calculate height of a tree. I mean normal tree, not any specific implementation of tree like BT or BST.
I have tried google but seems everyone is talking about Binary tree and nothing is available for normal tree.
Can anyone help me to redirect to some page or articles to calculate height of a tree.
Lets say a typical node in your tree is represented as Java class.
class Node{
Entry entry;
ArrayList<Node> children;
Node(Entry entry, ArrayList<Node> children){
this.entry = entry;
this.children = children;
}
ArrayList<Node> getChildren(){
return children;
}
}
Then a simple Height Function can be -
int getHeight(Node node){
if(node == null){
return 0;
}else if(node.getChildren() == null){
return 1;
} else{
int childrenMaxHeight = 0;
for(Node n : node.getChildren()){
childrenMaxHeight = Math.max(childrenMaxHeight, getHeight(n));
}
return 1 + childrenMaxHeight;
}
}
Then you just need to call this function passing the root of tree as argument. Since it traverse all the node exactly once, the run time is O(n).
1. If height of leaf node is considered as 0 / Or height is measured depending on number of edges in longest path from root to leaf :
int maxHeight(treeNode<int>* root){
if(root == NULL)
return -1; // -1 beacuse since a leaf node is 0 then NULL node should be -1
int h=0;
for(int i=0;i<root->childNodes.size();i++){
temp+=maxHeight(root->childNodes[i]);
if(temp>h){
h=temp;
}
}
return h+1;
}
2. If height of root node is considered 1:
int maxHeight(treeNode<int>* root){
if(root == NULL)
return 0;
int h=0;
for(int i=0;i<root->childNodes.size();i++){
temp+=maxHeight(root->childNodes[i]);
if(temp>h){
h=temp;
}
}
return h+1;
Above Code is based upon following class :
template <typename T>
class treeNode{
public:
T data;
vector<treeNode<T>*> childNodes; // vector for storing pointer to child treenode
creating Tree node
treeNode(T data){
this->data = data;
}
};
In case of 'normal tree' you can recursively calculate the height of tree in similar fashion to a binary tree but here you will have to consider all children at a node instead of just two.
To find a tree height a BFS iteration will work fine.
Edited form Wikipedia:
Breadth-First-Search(Graph, root):
create empty set S
create empty queues Q1, Q2
root.parent = NIL
height = -1
Q1.enqueue(root)
while Q1 is not empty:
height = height + 1
switch Q1 and Q2
while Q2 is not empty:
for each node n that is adjacent to current:
if n is not in S:
add n to S
n.parent = current
Q1.enqueue(n)
You can see that adding another queue allows me to know what level of the tree.
It iterates for each level, and for each mode in that level.
This is a discursion way to do it (opposite of recursive). So you don't have to worry about that too.
Run time is O(|V|+ |E|).

Find all nodes which are not Roman and all its descendents are roman in a binary tree

Problem:
Let T be a binary tree. Define a Roman node to be a node v in T, such that the number of descendants in v’s left subtree differs from the number of nodes in v’s right subtree by at most 5. Describe a linear-time algorithm for finding each node v of T, such that v is not a Roman node, but all of v’s descendants are Roman nodes.
What I have so far:
I could think of O(n^2) (top-down approach) solution where I will traverse the tree and check if a node is not roman, then traverse this node's descendants to check whether all of them are roman or not. So, in this way I am traversing each node twice.
I am assuming there is a bottom-up approach where it is possible to find the required node in O(n).
Any ideas?
Thanks #n.m. for your comments. I have implemented a solution using your inputs.
Logic:
The basic logic is to set isRoman field of a node to false even when a node's descendant (suppose grand grand child) is not roman. This means that even if a node satisfies the property (left and right descendants are at most 5) but if its left and right subtree's isRoman is false, then current node's isRoman will also be false.
/*
* public class TreeNode {
* int val;
* int size; //stores the number of descendants including itself
* boolean isRoman; // is true when this node is roman and all its descendants are roman,
* //false even when a grand grand child node of this node is not roman.
* TreeNode left;
* TreeNode right;
* }
*/
public static void roman(TreeNode root, List<TreeNode> lst){
if(root == null)
return;
if(root.left == null && root.right == null){
root.size = 1;
root.isRoman = true;
return;
}
int left = 0;
int right = 0;
boolean isLeftRoman = false;
boolean isRightRoman = false;
if(root.left != null) {
roman(root.left,lst);
left = root.left.size;
isLeftRoman = root.left.isRoman;
}else{
isLeftRoman=true;
}
if(root.right != null) {
roman(root.right,lst);
right = root.right.size;
isRightRoman = root.right.isRoman;
}else{
isRightRoman=true;
}
//if the current node is roman and all it's descendants are roman, update isRoman to true
if(Math.abs(left-right) <= 5 && isLeftRoman && isRightRoman)
root.isRoman = true;
else
root.isRoman = false;
//update the current node's size
root.size = left+right+1;
//add the node to list which is not roman but all its descendants are roman
if(Math.abs(left-right) > 5 && isLeftRoman && isRightRoman)
lst.add(root);
}

Computing rank of a node in a binary search tree

If each node in a binary search tree stores its weight (number of nodes in its subtree), what would be an efficient method to compute a rank of a given node (its index in the sorted list) as I search for it in the tree?
Start the rank at zero. As the binary search proceeds down from the root, add the sizes of all the left subtrees that the search skips by, including the left subtree of the found node.
I.e., when the search goes left (from parent to left child), it discovers no new values less than the searched item, so the rank stays the same. When it goes right, the parent plus all the nodes in the left subtree are less than the searched item, so add one plus the left subtree size. When it finds the searched item. any items in the left subtree of the node containing the item are less than it, so add this to the rank.
Putting this all together:
int rank_of(NODE *tree, int val) {
int rank = 0;
while (tree) {
if (val < tree->val) // move to left subtree
tree = tree->left;
else if (val > tree->val) {
rank += 1 + size(tree->left);
tree = tree->right;
}
else
return rank + size(tree->left);
}
return NOT_FOUND; // not found
}
This returns the zero-based rank. If you need 1-based then initialize rank to 1 instead of 0.
Since each node has a field storing its weight, the first you should implement a method call size() which return the number of nodes in a node's substree:
private int size(Node x)
{
if (x == null) return 0;
else return x.N;
}
then compute the rank of a given node is easy
public int rank(Node key)
{ return rank(key,root) }
private int rank(Node key,Node root)
{
if root == null
return 0;
int cmp = key.compareTo(root);
// key are smaller than root, then the rank in the whole tree
// is equal to the rank in the left subtree of the root.
if (cmp < 0) {
return rank(key, root.left)
}
//key are bigger than root,the the rank in the whole tree is equal
// to the size of subtree of the root plus 1 (the root) plus the rank
//in the right sub tree of the root.
else if(cmp > 0){
return size(root.left) + 1 + rank(key,root.right);
}
// key equals to the root, the rank is the size of left subtree of the root
else return size( root.left);
}
Depends on the BST implementation, but I believe you can solve it recursively.
public int rank(Key key){
return rank(root, key);
}
private int rank(Node n, Key key){
int count = 0;
if (n == null)return 0;
if (key.compareTo(n.key) > 0) count++;
return count + rank(n.left, key) + rank(n.right, key);
}

Link Tree nodes at each level

Given a binary tree, how would you join the nodes at each level, left to right.
Say there are 5 nodes at level three, link all of them from left to right.
I don't need anybody to write code for this.. but just an efficient algorithm.
Thanks
Idea is:
1. Traverse tree with BFS.
2. When you do traversing, you're linking nodes on next level - if node has left and right node, you'll link left to right. If node has next node, then you link rightmost child of current node to leftmost child of next node.
public void BreadthFirstSearch(Action<Node> currentNodeAction)
{
Queue<Node> q = new Queue<Node>();
q.Enqueue(root);
while (q.Count != 0)
{
Node current = q.Dequeue();
if (currentNodeAction != null)
currentNodeAction(current);
if (current.left != null) q.Enqueue(current.left);
if (current.right != null) q.Enqueue(current.right);
}
}
private void Linker(Node node)
{
Link(node.left, node.right);
if (node.next != null)
Link(node.right ?? node.left, node.next.left ?? node.next.right);
}
private void Link(Node node1, Node node2)
{
if (node1 != null && node2 != null)
node1.next = node2;
}
public void LinkSameLevel()
{
BreadthFirstSearch(Linker);
}
Create a vector of linked lists.
Do a DFS keeping track of your level, and for each node you find, add it to the linked list of the level.
This will run in O(n) which is optimal.
Is this what you want to do?
This is not a direct answer to the question and may not be applicable based on your situation. But if you have control over the creation and maintenance of the binary tree, it would probably be more efficient to maintain the links while building/updating the tree.
If you kept both left and right pointers at each level, then it would be "simple" (always easy to say that word when someone else is doing the work) to maintain them. When inserting a new node at a given level, you know its direct siblings from the parent node information. You can adjust the left and right pointers for the three nodes involved (assuming not at the edge of the tree). Likewise, when removing a node, simply update the left and right pointers of the siblings of the node being removed. Change them to point to each other.
I agree with Thomas Ahle's answer if you want to make all of the row-lists at the same time. It seems that you are only interested in making the list for a one specific row.
Let's say you have a giant tree, but you only want to link the 5th row. There's clearly no point in accessing any node below the 5th row. So just do an early-terminated DFS. Unfortunately, you still have to run through all of the ancestors of every node in the list.
But here's the good news. If you have a perfect binary tree (where every single node branches exactly twice except for the last row) then the first row will have 1 one, the second 2, the third 4, the fourth 8 and the fifth 16. Thus there are more nodes on the last row (16) than all the previous put together (1 + 2 + 4 + 8 = 15), so searching through all of the ancestors is still just O(n), where n is the number of nodes in the row.
The worst case on the other hand would be to have the fifth row consist of a single node with a full binary tree above it. Then you still have to search through all 15 ancestors just to put that one node on the list.
So while this algorithm is really your only choice without modifying your data structure its efficiency relies entirely on how populated the row is compared to higher rows.
#include <queue>
struct Node {
Node *left;
Node *right;
Node *next;
};
/** Link all nodes of the same level in a binary tree. */
void link_level_nodes(Node *pRoot)
{
queue<Node*> q;
Node *prev; // Pointer to the revious node of the current level
Node *node;
int cnt; // Count of the nodes in the current level
int cntnext; // Count of the nodes in the next level
if(NULL == pRoot)
return;
q.push(pRoot);
cnt = 1;
cntnext = 0;
prev = NULL;
while (!q.empty()) {
node = q.front();
q.pop();
/* Add the left and the right nodes of the current node to the queue
and increment the counter of nodes at the next level.
*/
if (node->left){
q.push(node->left);
cntnext++;
}
if (node->right){
q.push(node->right);
cntnext++;
}
/* Link the previous node of the current level to this node */
if (prev)
prev->next = node;
/* Se the previous node to the current */
prev = node;
cnt--;
if (0 == cnt) { // if this is the last node of the current level
cnt = cntnext;
cntnext = 0;
prev = NULL;
}
}
}
What I usually do to solve this problem is that I do a simple inorder traversal.
I initialize my tree with a constructor that gives a level or column value to every node. Hence my head is at Level 0.
public Node(int d)
{
head=this;
data=d;
left=null;
right=null;
level=0;
}
Now, if in the traversal, I take a left or a right, I simply do the traversal with a level indicator. For each level identifier, I make a Linked List, possibly in a Vector of Nodes.
Different approaches can be used to solve this problem. Some of them that comes to mind are -
1) Using level order traversal or BFS.
We can modify queue entries to contain level of nodes.So queue node will contain a pointer to a tree node and an integer level. When we deque a node we can check the level of dequeued node if it is same we can set right pointer to point to it.
Time complexity for this method would be O(n).
2) If we have complete binary tree we can extend Pre-Order traversal. In this method we shall set right pointer of parent before the children.
Time complexity for this method would be O(n).
3) In case of incomplete binary tree we can modify method (2) by traversing first root then right pointer and then left so we can make sure that all nodes at level i have the right pointer set, before the level i+1 nodes.
Time complexity for this method would be O(n^2).
private class Node
{
public readonly Node Left;
public readonly Node Right;
public Node Link { get; private set; }
public void Run()
{
LinkNext = null;
}
private Node LinkNext
{
get
{
return Link == null ? null : (Link.Left ?? Link.Right ?? Link.LinkNext);
}
set
{
Link = value;
if (Right != null)
Right.LinkNext = LinkNext;
if (Left != null)
Left.LinkNext = Right ?? LinkNext;
}
}
}
Keep a depth array while breadth-first search.
vector<forward_list<index_t>> level_link(MAX_NODES);
index_t fringe_depth = 0;
static index_t depth[MAX_NODES];
memset(depth,0,sizeof(depth));
depth[0] = 0;
Now when the depth-changes while de-queuing, you get all linked !
explored[0] = true;
static deque<index_t> fringe;
fringe.clear();
fringe.push_back(0); // start bfs from node 0
while(!fringe.empty()) {
index_t xindex = fringe.front();
fringe.pop_front();
if(fringe_depth < depth[xindex]) {
// play with prev-level-data
fringe_depth = depth[xindex];
}
Now we have fringe-depth, so we can level-link.
level_link[fringe_depth].push_front(xindex);
for(auto yindex : nodes[xindex].connected) {
if(explored[yindex])
continue;
explored[yindex] = true;
depth[yindex] = depth[xindex] + 1;
fringe.push_back(yindex);
}
}

Resources