a
/ \
b g
/ \
c d
/
e
\
f
public static Node createData() { //this is the nodes which make up the tree structure
Node a = new Node( "a");
Node b = new Node( "b");
Node c = new Node( "c");
Node d = new Node( "d");
Node e = new Node( "e");
Node f = new Node( "f");
Node g = new Node( "g");
a.left = b; //this block of code connects the nodes to the specific tree should look
a.right = g;
b.left = c;
b.right = d;
c.left = e;
e.right = f;
public static void preOrderTraversal(Node n) { // method recursively traverses through using preOrder
if(n == null)
return;
System.out.println(n.value + " ");
preOrderTraversal(n.left);
preOrderTraversal(n.right);
}
//I understand how a, b, c, and e are being outputted. However, once we reach the node e, n is a reference to a null value. So when we enter the method with a null value, after we enter the if statement, where exactly do we "return" to? Like where does the program sort of jump to/which line is now being looked at at this point? I am struggling to understand how the method works once n is a reference to a null value. By the way, preOrder Traversal has these 3 steps in this order: Visit Node, Traverse left, Traverse right. and then repeats recursively
Related
I traverse the nodes of a tree in depth-first manner. Suppose the tree is as follows:
Now, suppose that I am in node E and for some condition I want to back to the node C and continue from there. Then previous traversing should be canceled and node C, D, E should be evaluated again. Node F and G shouldn't be traversed twice as the previous recursive navigation has been cancelled!
Usual navigation : A B C D E F G
The desire navigation : A B C D E C D E F G
The general code of depth-first traversing is as follows:
void DFS(node x)
{
z = evaluate(x);
// if (z != null) DFS(z)
// Z could be a node which has been already traversed,
// let's suppose it's an ancestor of x
foreach (node y in c.children)
{
DFS(y);
}
}
Please help me how can I have such navigation in the tree?
I will try to outline a pseudocode using a global variable cancel.
boolean cancel = false;
void DFS(node x, parent p)
{
if(!cancel) {
foreach (node y in x.children) {
DFS(y, x);
}
} else {
cancel = false;
DFS(p, findParent(p));
}
}
However, there is a problem with this approach. Once the traversal has started in the foreach section, each subsequent call to the DFS method within the loop will invoke the DFS from parent node. To address this concern, I would recommend you to simulate the depth first traversal by using your own stack rather than taking the recursive approach. That way, when cancel becomes true, you can clear the stack and ensure that DFS call from the parent happens only once. Hope this helps!
Something among the following lines should work:
boolean cancel = false;
Stack<Node> s;
void DFSIterative(Node x, Node p) {
if(cancel) {
resetDFS(p);
} else {
s.push(x);
while(!s.isEmpty()) {
x = s.pop();
p = findParent(x);
if(cancel) resetDFS;
else {
foreach(node y in x.children) {
s.push(y);
}
}
}
}
}
void resetDFS(Node p) {
s.clear();
cancel = false;
DFSIterative(p, findParent(p));
}
I leave the implementation of findParent() helper method to you. Please note that you will also need to take care of marking the nodes as visited and then unmarking relevant nodes as unvisited when you cancel DFS.
Depending on how far back up the tree you want to go, something like this should work.
The DFS function returns the number of levels to retry:
0 to carry on as normal
1 to retry the same node
2 to retry the parent...
Code:
int DFS(node x)
{
if (some condition)
{
// return the number of parent levels you want to back up
return 2;
}
for (int i = 0; i < x.children.size; ++i)
{
int redo = DFS(x.children[i]);
if (redo == 1) {
// redo == 1 means retry the current node
--i;
}
if (redo > 1) {
{
// redo > 1 means retry an ancestor node
return redo - 1;
}
}
return 0;
}
Obviously you have to be careful with your condition, or you'll end up in an infinite loop.
With the base code as above, the following condition will return A B C D E C D E F G
boolean retryE = true;
int DFS(node x)
{
if (x.value == "E" && retryE)
{
retryE = false;
return 2;
}
// remaining code as above
}
Update
Looking again, if your evaluate function returns an ancestor node not a number of levels, this may be closer to what you originally wanted... Will fail if the node returned is not an ancestor of the current child...
// returns null to continue DFS, or a node value to repeat from that node
Node DFS(Node x)
{
Node z = evaluate(x)
if (z != null)
{
return z;
}
for (int i = 0; i < x.children.size; ++i)
{
Node child = x.children[i];
Node result = DFS(child);
if (result != null)
{
if (result == child)
{
// current child is the one to retry so just
// decrement the counter to retry it
--i;
} else {
// retry a node but not this child so return it up the stack
return result;
}
}
}
return null;
}
Update 2
Using the same DFS function, consider this evaluate function, which returns C for the first occurence of both E and F
boolean retryE = true;
boolean retryF = true;
evaluate(Node x)
{
if (x.value == "E" && retryE)
{
retryE = false;
return C;
}
if (x.value == "F" && retryF)
{
retryF = false;
return C;
}
return null;
}
This will work correctly using the --i decrement method (returning A B C D E - C D E F - C D E F G), but not if calling DFS(child) directly, unless the result of the second call is processed somehow.
Cheers
See here I can see that u have used a void DFS that is your function is not returning anything so you can use that value to check if something is need to be reevaluated.
Like this
int DFS(node x)
{
int ret=0;
z = evaluate(x);
// if (z != null) DFS(z) Z could be a node which has been already traversed
foreach (node y in c.children)
{
ret=DFS(y);
if(ret==1)
break;
}
if(ret==1)
DFS(x);
if(z==(want to reevaluate))
return 1;
else
return 0;
}
Now by this you can simply return to the parent 1 if you want it to redo the DFS on all its children and you can simply return 0 if you want it to simply continue.
If any of the children of A returned 1 in that case All the children and that node will be reevaluated and the nodes above it will continue in the same way as they were.
So by you image.If E returns 1 then all of the nodes C,D,E will be reevaluated. If you have return value fixed to return distance or something then this could be done using a variable also, you just need to send its address to all the children and watch for its value.
I am solving a problem in which I have to find the longest leaf-to-leaf path in a binary tree along with its length.
for example, if the Binary tree is as follows:
a
/\
b c
/ / \
d e f
/ \ \
g h p
\
k
The longest leaf-to-leaf path would be k-h-d-b-a-c-f-p which is of length 8.
I am calculating the length by recursively finding the length of the left and right sub-tree and then return height_left + height_right + 1 . Is my concept correct?.
Also how should I print the longest leaf-to-leaf path? I just want an idea to proceed.
It seems to me that this algorithm is very close to finding a diameter of a binary tree. Diameter of the tree is the number of nodes on the longest path between two leaves in the tree.
I think you can look here for the implementation: http://www.geeksforgeeks.org/diameter-of-a-binary-tree/ and then adapt it or optimize it's time complexity if you want. But i think O(n) is good enough.
Most answers on the net gives how to find diameter of a tree, i.e
How to find the number of nodes in the longest path.
The only addition is we need to store the nodes which contribute to it.
In recursion, this can be done in two ways.
a) It should be a return type
b) It should be an input parameter which is an object. This object is populated with the result during the course of recursion.
Without the need to print the longest path, we only need to check at every node:
Max of
1) Left node max path
2) Right node max path
c) Current node max path (requires more inputs)
Now, to calculate current node max path, we need more inputs:
Current node max path needs:
1) Max left node height
2) Max right node height
This can either be stored in the node itself (as height parameter) or can be passed with the recursion.
This will only give diameter/length of the longest path.
Now, to get the path printed, we need to store more info which is:
- List<Nodes> pathList - This contains the nodes which form the longest path so far (Note this may not contain the current node).
- List<Nodes> heightList - This contains the nodes which form the longest height from the node to its leaf.
Finally the algo:
//Inputs and Outputs of the method
class Node{
int value;
Node leftchild;
Node rightchild;
}
class ReturnInfo{
ReturnInfo(){
maxpathlen = 0;
maxheight = 0;
pathList = new ArrayList<Node>();
heightList = new ArrayList<Node>();
}
int maxpathlen; //current max path
int maxheight; //current max height
List<Nodes> pathList;
List<Nodes> heightList;
}
//Signature
public ReturnInfo getMaxPath(Node n);
//Implementation
public ReturnInfo getMaxPath(Node n){
//Base case
if(n==null) return new ReturnInfo();
//This is a bottom up recursion. Info will flow from leaves to root.
//So first recurse and then do the work at this node level
//Recurse left & right
ReturnInfo leftReturnInfo = getMaxPath(n.leftchild);
ReturnInfo rightReturnInfo = getMaxPath(n.rightchild);
//Do work in this recursion or for this node
ReturnInfo retInfo = new ReturnInfo();
//Update all 4 parameters of returninfo and we are done
retInfo.maxheight = max(leftReturnInfo.maxheight, rightReturnInfo.maxheight) + 1;
//Update retInfo.heightList accordingly
retInfo.heightList = ....
retInfo.maxPathLen = max(leftReturnInfo.maxPathLen, rigthReturnInfo.maxPathLen, leftReturnInfo.maxHeight+rightReturnInfo.maxHeight+1);
//Remember from where maxPathLen came from and update accordingly
retInfo.pathList = .....
return retInfo;//We are done
}
You need a function that returns longest branch in a subtree and the longest path:
PS: I am leaving out details (Eg. Boundary conditions and so on). But this should give you an idea. This function returns two things 'branch' and 'path'. 'branch' is the longest path from this node to any of its leaves. 'path' is the longest path between any two leaves in this subtree.
def longestPath(node):
(leftBranch, leftPath) = longestPath(node.left);
(rightBranch, rightPath) = longestPath(node.right);
if len(rightBranch) > len(leftBranch):
curBranch = rightBranch+node.name
else:
curBranch = leftBranch+node.name
curPath = leftBranch + node.name + rev(rightBranch)
bestPath = curPath
if len(leftPath) > length(bestPath):
bestPath = leftPath
if len(rightPath) > length(bestPath):
bestPath = rightPath
return (curBranch, bestPath)
defintion:
node: (char content, node left , node right , node parent)
add(list , node): add node as last element in list
remove(list , index): remove and return element at index in list
length(string): length of string
insert(string , char , index): insert char at index in string
concat(string a , string OR char b): append b to a
input: node start
output: string
start
list nodes
node n
add(nodes , start)
do
n = remove(nodes , 0)
if n.parent != null
add(nodes , n.parent)
if n.left != null
add(nodes , n.left)
if n.right != null
add(nodes , n.right)
while !isEmpty(nodes)
//n now is the node with the greatest distance to start
string left = ""
string right = ""
node a = start
node b = n
while(a != b)
insert(left , a.content , length(left) - 1)
insert(right , b.content , 0)
a = a.parent
b = b.parent
string result = left
concat(result , a.content)
concat(result , right)
return result
Here is my Scala solution (Tree.scala):
/** Searches for the longest possible leaf-to-leaf path in this tree.
*
* Time - O(log^2 n)
* Space - O(log n)
*/
def diameter: List[A] = {
def build(t: Tree[A], p: List[A]): List[A] =
if (t.isEmpty) p
else if (t.left.height > t.right.height) build(t.left, t.value :: p)
else build(t.right, t.value :: p)
if (isEmpty) Nil
else {
val ld = left.diameter
val rd = right.diameter
val md = if (ld.length > rd.length) ld else rd
if (1 + left.height + right.height > md.length)
build(right, value :: build(left, Nil).reverse).reverse
else md
}
}
The idea is quite simple:
We recursively search for diameters in children (ld and rd and maximum 'md').
Check whether the longest possibe path that goes through current node is greather then diameters of its children or not (if (1 + ....)).
If its greater then we just need to build a new path with build function, which bilds a longest path from given node 't' to leaf. So, we just concatenates two resuts of this function (for left and right child) with current node.
If its not greater then the diameter is found it is md.
Longest leaf to leaf path means finding diameter of a tree. It can be done using height function.
There are many solutions available online.
Here is my Swift solution:
func diameterPath() -> [T] {
return diameterPathHelper(root).Path
}
typealias HeightAndDiameterAndPath = (Height: Int, Diameter: Int, Path: [T])
private func diameterPathHelper(node: TreeNode<T>?) -> HeightAndDiameterAndPath {
guard let node = node else {
return HeightAndDiameterAndPath(0, 0, [])
}
let left = diameterPathHelper(node.left)
let right = diameterPathHelper(node.right)
let height = max(left.Height, right.Height) + 1
if left.Height + right.Height + 1 > max(left.Diameter, right.Diameter) {
let currentDiameter = left.Height + right.Height + 1
let path = left.Path + [node.data] + right.Path
return HeightAndDiameterAndPath(height, currentDiameter, path)
} else {
if left.Diameter > right.Diameter {
return HeightAndDiameterAndPath(height, left.Diameter, left.Path)
} else {
return HeightAndDiameterAndPath(height, right.Diameter, right.Path)
}
}
}
We can use the maxdepth approach for this and initialize a variable max as 0.
public int diameterOfBinaryTree(TreeNode root) {
maxDepth(root);
return max;
}
private int maxDepth(TreeNode root) {
if (root == null) return 0;
int left = maxDepth(root.left);
int right = maxDepth(root.right);
max = Math.max(max, left + right);
return Math.max(left, right) + 1;
}
}
You have neglected one condition: What if the longest path doesn't pass through the root node?
static int findLongestPathLength(Node root){
if(root == null)
return 0;
int lh = getHeight(root.left);
int rh = getHeight(root.right);
return Math.max(1+lh+rh,
Math.max(findLongestPathLength(root.left),findLongestPathLength(root.right)));
}
static int getHeight(Node root){
if(root == null)
return 0;
return Math.max(getHeight(root.left)+1, getHeight(root.right)+1);
}
This will also make sure it find the longest path even if it doesn't pass through root.
This question might have been asked by a lot of guys but, it is kinda different. We have a binary tree. And you are given two nodes p & q. We have to find the least common parent. But you dont have root node pointer which points to the root. You are provided with two inbuilt functions which are:
1) BOOL same(node *p, node *q); -> returns true if the nodes are same or else false.
2) node* parentNode(node *c); -> returns a node which is the parent of the current node.
If the node c is actually root then parentNode function will return you with aNULL value.
Using the functions we have to find the least common parent of the tree.
Step1: Using parentNode function find the distance d1 of the node p from root. similarly find distance d2 of node q from the root. (say, d2 comes out ot be greater than d1)
Step 2: Move the farther node(whose ever d-value was greater) pointer d2-d1 steps towards root.
Step3: Simultaneously move pointers p and q towards root till they point to same node and return that node.
Basically it will be like finding the merge point of two linked-lists. Check the below link:
Check if two linked lists merge. If so, where?
Time complexity: O(N)
Your code would look somewhat along the lines:
node* LCP(node* p, node *q){
int d1=0, d2=0;
for(node* t= p; t; t = parentNode(p), ++d1);
for(node* t= q; t; t = parentNode(q), ++d2);
if(d1>d2){
swap(d1, d2);
swap(p, q);
}
for(int i=0; i<(d2-d1); ++i)
q = parentNode(q);
if( same(p, q)){
return parentNode(p);
}
while( !same(p, q)){
p = parentNode(p);
q = parentNode(q);
}
return p;
}
Assuming C++:
node* leastCommonParent(node *p, node *q)
{
node *pParent = parentNode(p);
while(pParent != 0)
{
node *qParent = parentNode(q);
while(qParent != 0)
{
if (0 == same(pParent, qParent))
return pParent;
qParent = parentNode(qParent);
}
pParent = parentNode(pParent);
}
return 0;
}
UPDATE: A version without explicitly declared variables using recursion follows. I'm sure it can be improved and would probably never use it in production code in the current form.
node* qParent(node *p, node *q)
{
if (p == 0 || q == 0)
return 0;
if (same(p, q) == 0)
return p;
return qParent(p, q->parent);
}
node* pParent(node *p, node *q)
{
return qParent(p, q) ? qParent(p, q) : pParent(p->parent, q);
}
node * result = pParent(p, q);
I have a question i want to create postorder from inorder and preorder, but i don't wana use reconstruction of tree, i want only recursive do this. I code this, and at this moment, i have a part of, right side of tree in preorder( First char in preorder is root, i find this in inorder, and i have left and right side, i recurency translate to right side), but i have a problem with left side of tree. I don't have no idea to do this. Can someone give me some of suggestion or code ? Please help :)
public static String a(String pre, String in, int start, int end) {
char c = pre.charAt(start); //first char in preorder is root
int ix = find(pre, in, c); // if we find this char in inorder translation we know where is left and right side of tree
stack += c;
if (start == 0 && flaga == true) {
left = pre.substring(1, ix + 1);
right = pre.substring(ix + 1, end);
flaga = false;
return a(right, in, 0, end);
}
String reverse = new StringBuffer(stos).reverse().toString();
//stack to see
// System.out.println("STACK " + stos);
if (start < right.length()-1) {
return a(right, in, start + 1, end - 1);
}
return "";
}
public static int find(String a, String b, char c) {
int b_l = b.length();
for (int i = 0; i < b_l; ++i)
if (b.charAt(i) == c)
return i;
return -1;
First Test :
String pre = "FBADCEGIH";
String inorder = "ABCDEFGHI";
ANswer should be : //A, C, E, D, B, H, I, G, F
My problem is with left side of tree, i don't have any idea to do this correct, and i'm not sure my code work for all situation of preorder and inorder.
I am looking a way to find out inorder successor of a node in BST withut using extra space.
To get the inorder successor of a given node N we use the following rules:
If N has a right child R then the
inorderSuccessor(N) is the leftmost
decedent of R.
Else inorderSuccessor(N) is the closest
ancestor, M, of N (if it exists)
such that N is descended from the
left child of M. If there is no such ancestor, inorderSucessor does not exist.
Consider a sample tree:
A
/ \
B C
/ \
D E
/
F
Whose inorder traversal gives: D B F E A C
inorderSuccessor(A) = C as C is the leftmost decedent of the right child of A.
inorderSuccessor(B) = F as F is the leftmost decedent of the right child of B.
inorderSuccessor(C) = Does not exist.
inorderSuccessor(D) = B as B is the left child of D.
inorderSuccessor(E) = A. E does not have a right child so we have scenario 2. We go to parent of E which is B, but E is right decedent of B, so we move to parent of B which is A and B is left decedent of A so A is the answer.
inorderSuccessor(F) = E as F is the left child of E.
Procedure:
treeNodePtr inorderSucessor(treeNodePtr N) {
if(N) {
treeNodePtr tmp;
// CASE 1: right child of N exists.
if(N->right) {
tmp = N->right;
// find leftmost node.
while(tmp->left) {
tmp = tmp->left;
}
// CASE 2: No right child.
} else {
// keep climbing till you find a parent such that
// node is the left decedent of it.
while((tmp = N->parent)) {
if(tmp->left == N) {
break;
}
N = tmp;
}
}
return tmp;
}
// No IOS.
return NULL;
}
Code In Action
The following method helps you determine the inorder successor WITHOUT ANY PARENT NODE OR EXTRA SPACE NON-RECURSIVELY
struct node * inOrderSuccessor(struct node *root, struct node *n)
{
//*If the node has a right child, return the smallest value of the right sub tree*
if( n->right != NULL )
return minValue(n->right);
//*Return the first ancestor in whose left subtree, node n lies*
struct node *succ=NULL;
while(root)
{
if(n->datadata < root->data)
{
succ=root; root=root->left;
}
else if(n->data > root->data)
root=root->right;
else break;
}
return succ;
}
I'm quite certain this is right. Do correct me if I am wrong. Thanks.
If the given node has a right child - go to it, and then follow iteratively the left children until you reach a node N with no left children. Return N.
Otherwise, follow the parents until you first find a parent where the node is a left child. Return this parent.
Node InOrderSuccessor(Node node) {
if (node.right() != null) {
node = node.right()
while (node.left() != null)
node = node.left()
return node
} else {
parent = node.getParent();
while (parent != null && parent.right() == node) {
node = parent
parent = node.getParent()
}
return parent
}
}
If you can access the root of a node, then it's just a matter of moving pointers around, so no extra space. See this lecture.