How to identify a leaf of a tree? - data-structures

Say I have a tree, with N vertices, and N - 1 edges. The tree is constructed with the data given below. It contains a pair of integers, which represents the vertices that are connected by an edge. The tree is always rooted at 1.
Sample:
1 2
3 1
3
/
1
/
2
What are the leaf nodes in this example considering the tree is rooted at 1? Is this even a valid tree formation?

If 1 is the root, I'd say 2 and 3 are the leaves, but I would rather draw it this way:
1
/ \
2 3
or the other way around:
2 3
\ /
1

Leaf is a node that does not have a child node in the tree. Now coming back to your question :
Is this even a valid tree formation?
Yes it is a valid tree.
As per the above definition : The leaf nodes in the example (with tree rooted at 1) :
3
/
1
/
2
Leaf Nodes are : 2 and 3(as two and 3 have no child nodes).
Simple program to check a leaf node :
boolean isLeaf(Node node)
{
if(node == null)
return false;
return node.left == null && node.right == null;
}

Related

In a binary tree, for every node the difference between the number of nodes in the left and right

In a binary tree, for every node the difference between the number of nodes in the left and right subtrees is at most 2. If the height of the tree is h>0, then the minimum number of nodes in the tree is.
My Understanding:Total nodes in that tree = no.of left subtree nodes + no.of right subtree nodes + 1 ( root node)
= no.of left subtree nodes + ( no.of left subtree nodes - 2 ) + 1
= no.of left subtree nodes + no.of left subtree nodes - 2 + 1
= 2 * no.of left subtree nodes - 1
H(n) = 2*H(n-1)-1
here i solved it using substitution but when i put h(0)=1 it gives only 1 as answer not in terms of H. can you please help why i can't put h(0)=1 as my base condition because it also satisfy the given binary tree.
Your recurrence assumes that your tree has nodes.
H(n) = 2*H(n-1) - 1 assumes H(n-1) is defined. But for n=0, H(n-1) = H(-1) which doesn't make sense. So you need to establish your base case for H(0) which you can do with a simple argument.
So your recurrence would be the value of H when n = 0 and H(n) = 2*H(n-1) - 1 if n > 0.
Also, you should use >= in your argument. The left subtree could actually be bigger.
no. of left subtree nodes + no. of right subtree nodes + 1 >= no. of left subtree nodes + (no. of left subtree nodes - 2) + 1
When n=1, in the minimal case the left subtree from the root has 1 node, but the right subtree has 0 nodes and not -1 nodes like your reasoning would suggest.
For n>1, your reasoning is correct.
So you need to assume H(1)=2, and then you get the right results.

Center node in a tree (in a minimum sum of distances sense)

My problem is the following:
Given a tree (V, E), find the center node v such that sum{w in V}[dist(v,w)] is minimum, where dist(v,w) is the number of edges in shortest path from v to w. The algorithm should run in O(n) time (n being the number of nodes in a tree).
The questions here and here also ask for the center node but define it differently.
I haven't rigorously gone through the steps but I actually think that the solution to my problem should be similar to the solution of this problem.
However, I decided that I should share my problem with the community as it took me a while to navigate to the link, which however does not answer the question directly.
I came up with this solution:
1) Choose an arbitrary node as a root r, form a tree. For each subtree in this tree, calculate number of nodes in a subtree (the leaves are single-node-trees).
As an example for this tree
1
/ | \
2 3 4
/ \ \
5 6 7
/ \
8 9
the result would be
9
/ | \
5 1 2
/ \ \
1 3 1
/ \
1 1
2) Calculate the sum of distances for this chosen root. For the example, if you choose vertex 1 as a root, the sum of distances is
0 + 1 + 1 + 1 + 2 + 2 + 2 + 3 + 3 = 15
3) Traverse the tree in a depth-first-search manner. For example, starting from vertex 1, we traverse to vertex 4. We observe that for 7 nodes (1,2,3,5,6,8,9), we are getting further by 1 (add 7=9-2 to the score), for other 2 (4,7), we are getting closer by 1 (subtract 2). This gives the sum-of-distances equal to 15+(9-2)-2 = 20.
Suppose we traverse from 4 to 7 next. Now we get the sum of distances equal to 20+(9-1)-1 = 27 (getting further from 8 vertices, and getting closer to 1 vertex).
As another example if we traverse from 1 to 2, we get a sum of distances equal to 15+(9-5)-5 = 14. Vertex 2 is actually the solution for this example.
This would be my algorithm.
Each edge e={a,b} has the following properties:
a_count = number of nodes to a side (including a)
b_count = number of nodes to b side (including b)
a_sum = sum of distances from a to its subtree nodes
b_sum = sum of distances from b to its subtree nodes
a_count for node e={a,b} can be evaluated as following:
* get all edges of a, not including e, sum their a_count
* add 1 to the sum
a_sum for node e={a,b} can be evaluated as following:
* get all edges of a, not including e, sum their a_sum
* add a_count (it includes +1 for each enumerated edge and +1 for a)
You can freely do calculation in recursive function accepting node and direction parameters, saving obtained results in global array.
If you run this function on every edge of tree in both directions, you get full calculation for edges. Total time for all calculations is O(n), since once you get to some subtree, recursive nature will close the whole subtree in this direction and next calls will obtain result from global array, and you only do 2*n calls for your function.
For a node A final measure is sum of all B_count+B_sum of all edges connected to node. Do one run of this evaluation on nodes and select node with minimal value.

Calculate the number of nodes on either side of an edge in a tree

A tree here means an acyclic undirected graph with n nodes and n-1 edges. For each edge in the tree, calculate the number of nodes on either side of it. If on removing the edge, you get two trees having a and b number of nodes, then I want to find those values a and b for all edges in the tree (ideally in O(n) time).
Intuitively I feel a multisource BFS starting from all the "leaf" nodes would yield an answer, but I'm not able to translate it into code.
For extra credit, provide an algorithm that works in any general graph.
Run a depth-first search (or a breadth-first search if you like it more) from any node.
That node will be called the root node, and all edges will be traversed only in the direction from the root node.
For each node, we calculate the number of nodes in its rooted subtree.
When a node is visited for the first time, we set this number to 1.
When the subtree of a child is fully visited, we add the size of its subtree to the parent.
After this, we know the number of nodes on one side of each edge.
The number on the other side is just the total minus the number we found.
(The extra credit version of your question involves finding bridges in the graph on top of this as a non-trivial part, and thus deserves to be asked as a separate question if you are really interested.)
Consider the following tree:
1
/ \
2 3
/ \ | \
5 6 7 8
If we cut the edge between node 1 and 2, The tree will surely split into two tree because there is only one unique edge between two nodes according to tree property:
1
\
3
| \
7 8
and
2
/ \
5 6
So, now a is the number of nodes rooted at 1 and b is number of nodes rooted at 2.
> Run one DFS considering any node as root.
> During DFS, for each node x, calculate nodes[x] and parent[x] where
nodes [x] = k means number of nodes of sub-tree rooted at x is k
parent[x] = y means y is parent of x.
> For any edge between node x and y where parent[x] = y:
a := nodes[root] - nodes[x]
b := nodes[x]
Time and space complexity both O(n).
Note that n=b-a+1. Due to this, you don't need to count both sides of the edge. This greatly simplifies things. A normal recursion over the nodes starting from the root is enough. Since your tree is undirected you don't really have a "root", just pick one of the leaves.
What you want to do is to "go down" the tree until you reach the bottom. Then you count backwards from there. The leaf returns 1, and each recursive step sums the return values for each edge and then increment by 1.
Here is the Java code. Function countEdges() takes in the adjacency list of the tree as an argument also current node and the parent node of the current node(here parent node means that current node was introduced by parent node in this DFS).
Here edge[][] stores the number of nodes on one side of the edge[i][j], obviously the number of nodes on the other side will be equal to (total nodes - edge[i][j]).
int edge[][];
int countEdges(ArrayList<Integer> adj[], int cur, int par) {
// If current nodes is leaf node and is not the node provided by the calling function then return 1
if(adj[cur].size() == 1 && par != 0) return 1;
int count = 1;
// count the number of nodes recursively for each neighbor of current node.
for(int neighbor: adj[cur]) {
if(neighbor == par) continue;
count += countEdges(adj, neighbor, cur);
}
// while returning from recursion assign the result obtained in the edge[][] matrix.
return edge[par][cur] = count;
}
Since we are visiting each node only once in the DFS time complexity should be O(V).

What's wrong with the most cited binary tree depth calculation algorithm?

There is something that eats into my brain: how can the depth of the following tree
b
/ \
a c
be 3, after the most cited algorithm (here in Java):
int depth(Node n)
{
if(n == null)
{
return 0;
}
int lDepth = depth(n.left);
int rDepth = depth(n.right);
return 1 + ((lDepth > rDepth) ? lDepth : rDepth);
}
when the depth of a tree with only a single (root) node is 0 according to Wikipedia and many of my other sources where the depth is defined as length of path to the deepest node? Obviously, the length of the path to the deepest node for a tree with only a single node is 0, while the above algorithm will never yield anything smaller than 1.
Is the depth of a tree with a single root node 0 or is it 1? If it is 0 then the algorithm above is faulty, because it will yield 1.
I never thought such a trivial thing would turn inside out on me.
The height of a tree is usually defined as:
1. The number of edges on the longest path from the root to a leaf
or
2. The number of nodes on the longest path from the root to a leaf
Of course you can easily transform a result given by any of the above definitions to a result of the other - just subtract/add 1.
You are correct, that the first definition is used more frequently.
As you can see, the algorithm which you are according to, follows the second definition.

Prove binary tree properties using induction

I am having trouble proving binary tree properties using induction:
Property 1 - A tree with N internal nodes has a maximum height of N+1
base case - 0 internal nodes has a height of 0
assume - a tree with k internal nodes has a maximum height of k+1 where k exists in n
show - true for all k+1 or true for all k-1
Property 2 - A tree with a tree with N internal nodes has N + 1 leaf nodes
base case - 0 internal nodes has 1 leaf node (null)
assume - a tree with k internal nodes has k + 1 leaf nodes where k exists in n
show - true for all k+1 or true for all k-1
Is my setup correct? And if so, how do I actually show these things. Everything I have tried has just ended up becoming a mess. Thanks for the help
You're missing a few things.
For property 1, your base case must be consistent with what you're trying to prove. So a tree with 0 internal nodes must have a height of at most 0+1=1. This is true: consider a tree with only a root.
For the inductive step, consider a tree with k-1 internal nodes. If its height is at most k (assumed), adding one more node can only raise it to k+1, and no higher. So the k-internal-node tree has height at most k+1.
Property 2 is false. Counterexample:
5
4 6
3 7
2 8
5 internal nodes, 2 leaves.
So there's probably something different you wanted to prove.

Resources