After going through the basics of Binary Tree, I define it in C++ as below :
struct Node
{
int key;
Node *left;
Node *right;
}*left=NULL,*right=NULL;
int getDepth(Node* t)
{
if (t == NULL)
return 0;
else
{
int lDepth = getDepth(t->left);
int rDepth = getDepth(t->right);
if (lDepth > rDepth)
return(lDepth + 1);
else
return(rDepth + 1);
}
}
int main()
{
// root
Node* root = new Node();
root->key = 1;
// left subtree
root->left = new Node();
root->left->key = 2;
root->left->left = new Node();
root->left->left->key = 4;
root->left->right = new Node();
root->left->right->key = 5;
// right subtree
root->right = new Node();
root->right->key = 3;
}
Now If I try to find maximum height/depth using this code, it returns 3 instead of 2. What may be the reason? Also, Why I didn't find this way of assigning value to nodes anywhere?
Edit: Adding requested code
Two issues:
1. You're incorrectly setting up the struct Node.
To define a type Node where the members have initial values, your syntax is slightly wrong. Instead, do:
struct Node {
int key = 0;
Node *left = nullptr;
Node *right = nullptr;
};
2. The height of the tree is 3.
Here's a visual representation of the tree you've created. It has 3 levels.
1
/ \
2 3
/ \
4 5
Related
Here's a code snippet of a solution that calculates height of each node in a binary tree and stores the height in each node. The code traverse the tree recursively, and below is the Node constructor.
class Node {
public:
int height; // to be set by computeHeight()
Node *left, *right;
Node() { height = -1; left = right = nullptr; }
~Node() {
delete left;
left = nullptr;
delete right;
right = nullptr;
}
};
Below is the function which computes and stores height at each Node. Where I am confused is how do leftHeight and rightHeight get updated by n->left->height and n->right->height if at construction, height is set to -1?
void computeHeight(Node *n) {
if (n == nullptr) {
return;
}
computeHeight(n->left);
computeHeight(n->right);
int leftHeight = -1;
int rightHeight = -1;
if (n->left != nullptr) {
leftHeight = n->left->height;
}
if (n->right != nullptr) {
rightHeight = n->right->height;
}
n->height = std::max(leftHeight, rightHeight) + 1;
}
Here is the main file that runs the function computeHeight
int main() {
Node *n = new Node();
n->left = new Node();
n->right = new Node();
n->right->left = new Node();
n->right->right = new Node();
n->right->right->right = new Node();
n->right->right->right->left = new Node();
computeHeight(n);
delete n;
n = nullptr;
return 0;
}
Imagine a leaf node (left and right are nullptr). Then n->left != nullptr and n->right != nullptr are false so the calculation effectively becomes
int leftHeight = -1;
int rightHeight = -1;
n->height = std::max(leftHeight, rightHeight) + 1;
which is effectively
n->height = 0;
Now because of the way the recursion is done, each node gets it height calculated after it's children have had their heights calculated. So imagine a node with two children, each of which is a leaf node. We've already seen that leaf nodes get a height of zero. So the calculation for such a node is effectively
int leftHeight = -1;
int rightHeight = -1;
if (n->left != nullptr) {
leftHeight = 0; // because n->left is a leaf node
}
if (n->right != nullptr) {
rightHeight = 0; // because n->right is a leaf node
}
n->height = std::max(leftHeight, rightHeight) + 1;
which means that you end up with n->height = 1 for that node.
And so on. These calculations perculate up the tree, starting at the leaves, until finally the root gets it's height set.
We can solve this problem with a basic case of induction. Basically, let's start with the base case, and then assuming any case n works, we have to check if case n+1 works. In the case of calculating the heights of the nodes in a Binary Tree, the base case is when the root node is a leaf node, and for the n+1 case the left/right side nodes are the n cases. You can think of it as n is the height of the current node, and n=0 is the leaf node base case.
When the root node is a leaf, both the left and right side nodes are nullptr the method essentially turns into
void computeHeight(Node *n) {
int leftHeight = -1;
int rightHeight = -1;
n->height = std::max(leftHeight, rightHeight) + 1;
}
in which case n->height becomes 0, which is correct for a leaf node. Now, when the node is a non-leaf node, the statements
computeHeight(n->left);
computeHeight(n->right);
are already called before the calculation. This essentially makes it so that we assume that both the left and right side nodes are already taken care of, and their heights are correct. Then, we can use the left and right nodes' heights to calculate the root node's height, which is calculated through
int leftHeight = -1;
int rightHeight = -1;
if (n->left != nullptr) {
leftHeight = n->left->height;
}
if (n->right != nullptr) {
rightHeight = n->right->height;
}
n->height = std::max(leftHeight, rightHeight) + 1;
The trick here is that we already have called computeHeight() on the left and right side nodes so that when we do the calculations on the current node, we can safely assume that the child nodes have been totally taken care of. Also, the child nodes are calculated before the root node, so the program will first trickle all the way down to the leaves before coming back up and calculating the non-leaf nodes.
I am trying to find the height of a binary tree and here is my attempt at the same
#include<iostream>
#include<stack>
using namespace std;
int total = 0;
int length = -1;
class Node{
public:
int data;
Node *left;
Node *right;
Node(int k){
data = k;
left = right = NULL;
}
};
void height(Node *root){
if(root==NULL)
return;
length++;
if(length>total)
total = length;
height(root->left);
height(root->right);
}
int main(){
Node *root = new Node(3);
root->left = new Node(4);
root->left->left = new Node(5);
root->right = new Node(6);
root->right->left = new Node(7);
height(root);
cout<<total;
return 0;
}
here length and total have been declared as global variables having values -1 and 0 respectively.
When I run the code, the output which I am getting is the number of nodes in the tree - 1 but not the height of the tree. Please let me know my mistake here.
Sure, you're incrementing length on every node.
If you're doing it recursively, it is actually very simple:
std::size_t height(Node const *root) {
if(!root) return 0;
return 1 + std::max(height(root->left), height(root->right));
}
Your approach is more of a backtracking than a simple recursion. In this approach you should be mindful to revert back to the original state at each step. Here length is always being incremented. You should revert it back.
void height(Node *root){
if(root==NULL)
return;
length++;
total = std::max(total,length+1); // Either this or initialize length as 0
height(root->left);
height(root->right);
length--; // <--- Add this line
}
I am struggling to understand how the following maxDepth function, which calculates the height of a tree, actually works.
Consider the tree:
1
/ \
2 3
/ \
4 5
\
8
In the code below, when we call the maxDepth function with the argument root, what is actually being calculated?
We declare two variables:
int lDepth = maxDepth(node->left);
int rDepth = maxDepth(node->right);
so for root we are assigning:
int lDepth = maxDepth(2);
int rDepth = maxDepth(3);
but there are no actual numeric values in here, so how do we call if (lDepth > rDepth) below this? There isn't anything to actually compare the values of is there? I would have thought the code in the if statement shouldn't execute.
#include <iostream>
using namespace std;
class node
{
public:
int data;
node* left;
node* right;
};
int maxDepth(node* node)
{
if (node == nullptr)
return 0;
else
{
/* compute the depth of each subtree */
int lDepth = maxDepth(node->left);
int rDepth = maxDepth(node->right);
/* use the larger one */
if (lDepth > rDepth)
return(lDepth+1);
else return(rDepth+1);
}
}
node* newNode(int data)
{
node* Node = new node();
Node->data = data;
Node->left = nullptr;
Node->right = nullptr;
return(Node);
}
int main()
{
node *root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
root->left->right->right = newNode(8);
cout << "Height of tree is " << maxDepth(root);
return 0;
}
We declare two variables:
int lDepth = maxDepth(node->left);
int rDepth = maxDepth(node->right);
so for root we are assigning:
int lDepth = maxDepth(2);
int rDepth = maxDepth(3);
No. We are instead finding the depths of two trees
2
/ \
4 5
\
8
and
3
The maxDepth() is a recursive function. So at the second level (one level lower to the root), there are two nodes 2 and 3.
Look at node 3 first, maxDepth(3) will allocate and call itself, then check whether there's a pointer or not, sincere there's not, it will return 0 from
if (node == nullptr)
return 0;
So rDepth is 0 for the node is 3.
Similarly, for the node 2, it will do the same, with multiple self-callings and assign an integer to the lDepth.
Thinking maxDepth() as an object instead of function might help.
I have a code that can determine tree height by hard coding it's values
I tried using container like structures but still was not successful, instead of posting what I have tried on the part of accepting tree nodes fro the Input which is actually messy,I decided to post the code with hard coded tree nodes, what I need is for the program to accept tree nodes from the keyboard with the following helper description for input
Input:
The first line is an integer N indicating the number of nodes.
For each of the next few lines, there are two integers include a and b.b is a child of a.
example:
5 // number of nodes
1 2
1 3
3 4
3 5
in which the height will be 3
// C++ program to find height of 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;
};
/* Compute the "maxDepth" of a tree -- the number of
nodes along the longest path from the root node
down to the farthest leaf node.*/
int maxDepth(node* node)
{
if (node == NULL)
return 0;
else
{
/* compute the depth of each subtree */
int lDepth = maxDepth(node->left);
int rDepth = maxDepth(node->right);
/* use the larger one */
if (lDepth > rDepth)
return(lDepth + 1);
else return(rDepth + 1);
}
}
/* 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);
}
// 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 << "Height of tree is " << maxDepth(root);
return 0;
}
Since the input identifies the parent node by its data value, we need a helper function to find it:
node *findNode(node *node, int data)
{
if (!node) return 0;
if (node->data == data) return node;
class node *found;
(found = findNode(node->left, data)) || (found = findNode(node->right, data));
return found;
}
Then we can code the input processing, e. g.:
node *node, *root = 0; // initially empty
int nn, a, b;
cin>>nn;
while (cin>>a>>b)
{
if (!root)
root = newNode(a),
node = root;
else
node = findNode(root, a);
if (!node->left) node->left = newNode(b);
else node->right = newNode(b);
}
I tried to implement C++ singly linked. I have created a method which creates a node and add a value and points to another node but i have to remember index.
How to improve the code and create nodes without remembering index? (I want to maintain order = first created node points to another etc.)
Class method:
void LinkedList::addValue ( int val )
{
if ( ! index )
{
n = new Node();
head = n;
n->value = val;
n->next = NULL;
}
else
{
n->next = new Node( );
n = n->next;
n->value = val;
}
++index;
}
I guess, you already have two member variables: head which is the root node and n which is the last node. You should initialize both of them with NULL (nullptr for c++11) in constructor. Then you can just check if n==NULL when you add a new value to the list.
LinkedList::LinkedList():head(NULL),n(NULL)
{}
void LinkedList::addValue ( int val )
{
if (n==NULL)
{
n = new Node();
head = n;
n->value = val;
n->next = NULL;
}
else
{
n->next = new Node( );
n = n->next;
n->value = val;
}
}
The index variable, however, can be useful if you want to find the list size in one fast read operation without iterating over all its nodes.
You can create another pointer called Tail to point to the last element. That way you can add value to the list without the index.
I call this method append
void append(int val){
void append(int val) {
Node* tmp = new Node(); // creating a temporary pointer to a new node
tmp -> value = val
last -> next = tmp; // connect the new node to the linked list
last = tmp; // set the last to the newly created node
listSize++; // increase the size of the list
}
You can also improve the code by making a Constructor for the node:
Class Node{
public:
int value;
Node * next;
Node(Node * nextEle = NULL) {
next = nextEle;
}
Node(int val,Node * nextEle = NULL) {
value = val;
next = nextEle;
}
}