Inorder tree traversal: Which definition is correct? - data-structures

I have the following text from an academic course I took a while ago about inorder traversal (they also call it pancaking) of a binary tree (not BST):
Inorder tree traversal
Draw a line around the outside of the
tree. Start to the left of the root,
and go around the outside of the tree,
to end up to the right of the root.
Stay as close to the tree as possible,
but do not cross the tree. (Think of
the tree — its branches and nodes — as
a solid barrier.) The order of the
nodes is the order in which this line
passes underneath them. If you are
unsure as to when you go “underneath”
a node, remember that a node “to the
left” always comes first.
Here's the example used (slightly different tree from below)
However when I do a search on google, I get a conflicting definition. For example the wikipedia example:
Inorder traversal sequence: A, B, C,
D, E, F, G, H, I
(leftchild,rootnode,right node)
But according to (my understanding of) definition #1, this should be
A, B, D, C, E, F, G, I, H
Can anyone clarify which definition is correct? They might be both describing different traversal methods, but happen to be using the same name. I'm having trouble believing the peer-reviewed academic text is wrong, but can't be certain.

In my bad attempt at the drawing here's the order that shows how they should be picked.
pretty much pick the node that is directly above the line being drawn,.

Forget the definitions, it's so much easier to just apply the algorithm:
void inOrderPrint(Node root)
{
if (root.left != null) inOrderPrint(root.left);
print(root.name);
if (root.right != null) inOrderPrint(root.right);
}
It's just three lines. Rearrange the order for pre- and post- order.

If you read carefully you see that the first "definition" says to start left of the root and that the order of the nodes is determined by when you pass under them. So B is not the first node, as you pass it from the left on the way to A, then first pass under A after which you go up and pass under B. Therefore it seems that both definitions give the same result.

I personally found this lecture quite helpful.

Both definitions give the same result. Don't be fooled by the letters in the first example - look at the numbers along the path. The second example does use letters to denote the path - perhaps that is what is throwing you off.
For example, in your example order showing how you thought the second tree would be traversed using the algorithm of the first one, you place "D" after "B" but you shouldn't because there is still a left-hand child node of D available (that's why the first item says "the order in which this line passes underneath them."

this may be late but it could be useful for anyone later ..
u just need not to ignore the dummy or null nodes e.g the Node G has a left null node .. considering this null node will make every thing alright ..

The proper traversal would be: as far left as possible with leaf nodes (not root nodes)
Left Root Right
A B NULL
C D E
Null F G
H I NULL
F is root or left, i am not sure

I think the first binary tree with the root of a is a Binary tree which is not correctly constructed.
Try to implement so that all the left side of the tree is less than the root and all the right side of the tree is greater than or equal to the root.

But according to (my understanding of)
definition #1, this should be
A, B, D, C, E, F, G, I, H
Unfortunately, your understanding is wrong.
Whenever you arrive at a node, you must descend to an available left node, before you look at the current node, then you look at an available right node.
When you chose D before C, you didn't descend to the left node first.

Hey according to me as mentioned in wiki is correct the sequence for a inorder traversal is left-root-right.
Till A, B, C, D, E, F i think you have understood already. Now after root F the next node is G that doesn't hav a left node but a right node so as per the rule (left-root-right) its null-g-right. Now I is the right node of G but I has a left node hence the traversal would be GHI. This is correct.
Hope this helps.

For an inline tree traversal you have to keep in mind that the order of traversal is left-node-right. For the above diagram that you are conflicted on, your error occurs when you read a parent node before reading any leaf(children) nodes to the left.
The proper traversal would be: as far left as possible with leaf nodes(A), return to parent node(B), move to the right, but since D has a child to its left you move down again(C), back up to C's parent(D), to D's right child(E), reverse back to the root(F), move to the right leaf(G), move to G's leaf but since it has a left leaf node move there(H), return to parent(I).
the above traversal reads the node when I have it listed in parenthesis.

package datastructure;
public class BinaryTreeTraversal {
public static Node<Integer> node;
public static Node<Integer> sortedArrayToBST(int arr[], int start, int end) {
if (start > end)
return null;
int mid = start + (end - start) / 2;
Node<Integer> node = new Node<Integer>();
node.setValue(arr[mid]);
node.left = sortedArrayToBST(arr, start, mid - 1);
node.right = sortedArrayToBST(arr, mid + 1, end);
return node;
}
public static void main(String[] args) {
int[] test = new int[] { 1, 2, 3, 4, 5, 6, 7 };
Node<Integer> node = sortedArrayToBST(test, 0, test.length - 1);
System.out.println("preOrderTraversal >> ");
preOrderTraversal(node);
System.out.println("");
System.out.println("inOrderTraversal >> ");
inOrderTraversal(node);
System.out.println("");
System.out.println("postOrderTraversal >> ");
postOrderTraversal(node);
}
public static void preOrderTraversal(Node<Integer> node) {
if (node != null) {
System.out.print(" " + node.toString());
preOrderTraversal(node.left);
preOrderTraversal(node.right);
}
}
public static void inOrderTraversal(Node<Integer> node) {
if (node != null) {
inOrderTraversal(node.left);
System.out.print(" " + node.toString());
inOrderTraversal(node.right);
}
}
public static void postOrderTraversal(Node<Integer> node) {
if (node != null) {
postOrderTraversal(node.left);
postOrderTraversal(node.right);
System.out.print(" " + node.toString());
}
}
}
package datastructure;
public class Node {
E value = null;
Node<E> left;
Node<E> right;
public E getValue() {
return value;
}
public void setValue(E value) {
this.value = value;
}
public Node<E> getLeft() {
return left;
}
public void setLeft(Node<E> left) {
this.left = left;
}
public Node<E> getRight() {
return right;
}
public void setRight(Node<E> right) {
this.right = right;
}
#Override
public String toString() {
return " " +value;
}
}
preOrderTraversal >>
4 2 1 3 6 5 7
inOrderTraversal >>
1 2 3 4 5 6 7
postOrderTraversal >>
1 3 2 5 7 6 4

void
inorder (NODE root)
{
if (root != NULL)
{
inorder (root->llink);
printf ("%d\t", root->info);
inorder (root->rlink);
}
}
This the most simplest approach to recursive definition of in-order traversal, just call this function in the main function to get the in-order traversal of a given binary tree.

It is correct for preorder,nt for inorder

Related

Binary tree Inorder traversal from only postorder traversal provided

I got a question in my coding challenge.
A complete binary tree is a binary tree where every node except the leaf node has two child nodes and the last level of the tree for an edge-height h has 2^h leaf-nodes.
Your task is simple, given the post-order traversal for a complete binary tree, print its in-order traversal.
The elements in the binary tree are of type character i.e. each node stores one character value.
Format of input / output
Input Format:
Only one string input denoting the postorder traversal.
Constraints:
1 <= input.length <= 1000
Output Format:
output one string that denotes the inorder traversal of the binary tree
Sample
Sample Input 0:
BCA
Sample Output 0:
BAC
I did have a full answer ready to go, but #EricWang beat me to the implementation. So here's a supplementary answer describing the process in more detail. Please accept his as the answer.
I'm going to use the post-order traversal DEBFGCA, as it's useful to consider slightly more nodes.
Because the tree is complete, for any given node we know that the the number of children on the left is the same as the number of children on the right. Therefore we can look at the post-order traversal DEBFGCA and know that it has the structure LLLRRRN, where L is the post-order traversal of the left subtree, R is the post-order traversal of the right subtree, and N is the node itself.
More generally, we know that the post-order traversal of the left subtree is characters 0 to (tree.length - 1)/2 - 1, and the post-order traversal of the right subtree is characters (tree.length -1)/2 - 1 to tree.length - 2. The node is the last character, at tree.length - 1.
Obviously, to change this to an in-order traversal, we just have to identify the left and right subtrees, change them to in-order traversal, and then return LLLNRRR. We can use recursion to convert the left and right subtrees to in-order.
So for example, start with DEBFGCA. We know the structure is LLLRRRN, so the left subtree is DEB, the right subtree is FGC, and the node is A. We want to turn DEB into in-order...
Process DEB. We know the left subtree is D, right is E, node is B. Both subtrees have length 1, so are leaves. No further recursion required. Return LNR, which is DBE.
Process FGC. As before, return FCG.
Now we know the in-order left is DBE and right is FCG. Return LLLNRRR, which is DBEAFCG.
You can do it dynamically, with recursion.
Mechanism
Split a tree to 3 parts: left, right, root.
Re-join them in order: left, root, right.
Split recursively, till the length of subtree is one.
Code - in Java
PostToInOrder.java
public class PostToInOrder {
public static String convert(String post) {
checkPerfect(post); // check whether tree is perfect,
return convertInner(post);
}
private static String convertInner(String post) {
int len = post.length();
if (len == 1) return post; // base case,
String left = post.substring(0, len >> 1); // left of post,
String right = post.substring(len >> 1, len - 1); // right of post,
char root = post.charAt(len - 1); // root of post,
return convertInner(left) + root + convertInner(right);
}
private static void checkPerfect(String tree) {
if (!isPerfect(tree)) throw new IllegalArgumentException("input is not perfect tree, size: " + tree.length());
}
private static boolean isPerfect(String tree) {
int len = tree.length();
if (len < 1) return false;
while (len != 0) {
if ((len & 1) == 0) return false;
len >>= 1;
}
return true;
}
}
PostToInOrderTest.java:
(Unit test, via TestNG)
import org.testng.Assert;
import org.testng.annotations.Test;
public class PostToInOrderTest {
#Test
public void test() {
Assert.assertEquals(PostToInOrder.convert("BCA"), "BAC");
Assert.assertEquals(PostToInOrder.convert("02146538A9CEDB7"), "0123456789ABCDE");
Assert.assertEquals(PostToInOrder.convert("A"), "A"); // single element,
}
#Test(expectedExceptions = IllegalArgumentException.class)
public void test_invalid_empty() {
PostToInOrder.convert("");
}
#Test(expectedExceptions = IllegalArgumentException.class)
public void test_invalid_notPerfect() {
PostToInOrder.convert("AB");
}
}
BTW:
The tree described in question is a perfect binary tree.
It's a sub type of complete binary tree.
A complete tree is not necessary perfect, its last level could lack of some leaves.
e.g AB is a complete tree, but not perfect tree.

How to find the leaf-only parent nodes in an n-ary tree

I'm trying to solve the following algorithm:
You have an n-ary tree. Find all the nodes satisfying the following
condition:
the node has child node(s) but all of the child nodes are leafs (they have no children ). Return a list of leaf only parent nodes and
their depth in the tree.
So if I have the tree below, the only node satisfying the above condition is D, because it has descendants (E) but they don't have children.
I am root!
/\ \
A B F
/\
C D
\
E
I'm trying to implement this in Java but pseudocode will also work for me.
I have the tree and node structures implemented here: N-ary trees in Java.
All I need is the algorithm.
start at root
while left son exists : go to left son
go back to father and check next son
if has no other sons : insert father to list
else insert father to list and go to step 2 but keep a depth counter and if found grandchildren : remove father from list
if finished all nodes : return list
root
/ \ \
A B F
/ \
C D
\
E
run example:
go to A
go back to root and insert root to list
go to B
go to C (remove root from potential because of counter)
go back to B and add B to list
go to D
go to E (remove B from potential because of counter)
go back to D and insert to list
go back to B
go back to root
go to F (don't insert root because root was already inserted [and removed]
return list which has only D
To make this work you should have a counter running for the node you are checking (to see if grandchildren exist) and also you should have a way of knowing if a node has been removed from the list so you would not insert it again (I didn't explicitly write it but I used 2 list - 1 for potentials and 1 for final)
OK, I got it. Here's the solution I've reached. I'm sure there are better solutions though - you're welcome to correct me.
// kick off the recursion
public Map<Integer, Integer> findLeafOnlyParents(GenericTree<Integer> tree){
Map<Integer, Integer> resultMap = new HashMap<>();
// start search from the root
traverseWithDepth(tree.getRoot(), resultMap, 0);
return resultMap;
}
private void traverseWithDepth(GenericTreeNode<Integer> node, Map<Integer, Integer> traversalResult, int depth) {
// check if the current note in the traversal is parent Of leaf-only nodes
if (isParentOfLeafOnly(node)){
traversalResult.put(node.data, depth);
}
// check the node's children
for(GenericTreeNode<Integer> child : node.getChildren()) {
traverseWithDepth(child, traversalResult, depth + 1);
}
}
// the main logic is here
private boolean isParentOfLeafOnly(GenericTreeNode<Integer> node){
boolean isParentOfLeafOnly = false;
// check if the node has children
if(node.getChildren().size() > 0){
// check the children of the node - they should not have children
List<GenericTreeNode<Integer>> children = node.getChildren();
boolean grandChildrenExist = false;
// for each child check if it has children of its own
for(GenericTreeNode<Integer> child : children) {
grandChildrenExist = child.getChildren().size() > 0;
// once found note that the current node has grandchildren,
// so we don't need to check the rest of the children of the node
if (grandChildrenExist){
break;
}
}
// we need only the parents who don't have great children
isParentOfLeafOnly = !grandChildrenExist;
}
return isParentOfLeafOnly;
}

How do i calculate space complexity for checking if binary search tree is balanced?

I want to check if binary search tree provided to me is balanced or not.
Since tree already exists in memory, there is no additional storage needed while checking if tree is balanced when traversing through nodes.
So I assume space complexity would be O(1).
Is it correct?
// Definition for binary tree
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
public class Solution {
public boolean isBalanced(TreeNode root) {
if (root == null)
return true;
if (getHeight(root) == -1)
return false;
return true;
}
public int getHeight(TreeNode root) {
if (root == null)
return 0;
int left = getHeight(root.left);
int right = getHeight(root.right);
if (left == -1 || right == -1)
return -1;
if (Math.abs(left - right) > 1) {
return -1;
}
return Math.max(left, right) + 1;
}
}
Your algorithm is O(height) space, not O(1) - you need to store 1 recursive function call in memory for every node as you recurse down the tree, and you can never go deeper than O(height) in the tree (before you return and can get rid of the already-fully-processed nodes).
For a tree like:
(Image reference - Wikipedia)
Your calls will go like this:
getHeight(8)
getHeight(3)
getHeight(1)
getHeight(6)
getHeight(4)
getHeight(7)
getHeight(10)
getHeight(14)
getHeight(13)
Here, getHeight(8) calls getHeight(3), which calls getHeight(1) and getHeight(6), etc.
After we've finished calling the function for 1 (returning the result to the call for 3), we don't need to keep that in memory any more, thus the maximum number of calls that we keep in memory is equal to the height of the tree.
It can be done in O(1) space, but it's fairly complicated and really slow (much slower than the O(n) that your solution takes).
The key is that we have a binary search tree, so, given a node, we'd know whether that node is in the left or right subtree of any ancestor node, which we can use to determine the parent of a node.
I may create a separate Q&A going into a bit more details at some point.

Connect nodes at same level using constant extra space

Objective:To write a function to connect all the adjacent nodes at the same level in a binary tree. Structure of the given Binary Tree node is like following.
struct node{
int data;
struct node* left;
struct node* right;
struct node* nextRight;
}
Initially, all the nextRight pointers point to garbage values. Function should set these pointers to point next right for each node.
Solution:
void connectRecur(struct node* p);
struct node *getNextRight(struct node *p);
// Sets the nextRight of root and calls connectRecur() for other nodes
void connect (struct node *p)
{
// Set the nextRight for root
p->nextRight = NULL;
// Set the next right for rest of the nodes (other than root)
connectRecur(p);
}
/* Set next right of all descendents of p. This function makes sure that
nextRight of nodes ar level i is set before level i+1 nodes. */
void connectRecur(struct node* p)
{
// Base case
if (!p)
return;
/* Before setting nextRight of left and right children, set nextRight
of children of other nodes at same level (because we can access
children of other nodes using p's nextRight only) */
if (p->nextRight != NULL)
connectRecur(p->nextRight);
/* Set the nextRight pointer for p's left child */
if (p->left)
{
if (p->right)
{
p->left->nextRight = p->right;
p->right->nextRight = getNextRight(p);
}
else
p->left->nextRight = getNextRight(p);
/* Recursively call for next level nodes. Note that we call only
for left child. The call for left child will call for right child */
connectRecur(p->left);
}
/* If left child is NULL then first node of next level will either be
p->right or getNextRight(p) */
else if (p->right)
{
p->right->nextRight = getNextRight(p);
connectRecur(p->right);
}
else
connectRecur(getNextRight(p));
}
/* This function returns the leftmost child of nodes at the same level as p.
This function is used to getNExt right of p's right child
If right child of p is NULL then this can also be used for the left child */
struct node *getNextRight(struct node *p)
{
struct node *temp = p->nextRight;
/* Traverse nodes at p's level and find and return
the first node's first child */
while(temp != NULL)
{
if(temp->left != NULL)
return temp->left;
if(temp->right != NULL)
return temp->right;
temp = temp->nextRight;
}
// If all the nodes at p's level are leaf nodes then return NULL
return NULL;
}
What will be the time complexity of this solution?
It is O(n^2) because of the getNextRight.
Easiest to see is to consider you have a complete binary tree. The number of leafs is O(n/2) so O(n). You get to call getNextRight for each leaf.
The first getNextRight is going to be for the last leaf on the right. That takes no passes through the while loop.
Next, you call getNextRight for the next to last leaf on the right. That takes 1 pass through the while loop.
For the next leaf you get 2 passes through the while loop. And so on... you get O(1 + 2 + 3 + ... + n/2) which is O(n^2).
Also the space complexity is not really constant. It is O(log n) if the tree is balanced because of the recursion. You may have a log n sized stack. If the tree is not balanced it will be even worst.
What appears to me is that you are connecting the nodes level-wise starting from the root node.
At any level since the parents have already been connected, you simply reach out to the next branch through the parents. Hence you are accessing each node only once (or twice through a child) at most.
Hence to me, the order of time complexity seems to be O(n) where n is the total number of elements in the tree.
I provided an answer to a similar question here on stackoverflow, using level-order traversal. Space and time complexity is O(n)

Breadth First Search and Depth First Search

Can anybody give a link for a simple explanation on BFS and DFS with its implementation?
Depth First Search:
Lets say you are given the following structure:
Format: Node [Children]
A [B C D]
B [E F]
C [G]
D []
E []
F []
G []
A breadth first search visits all of a node's children before visiting their children. Here's the pseudocode and the solution for the above structure:
1. Enqueue root node.
2. Dequeue and output. If the queue is empty, go to step 5.
3. Enqueue the dequeued node's children.
4. Go to Step 2.
5. Done
Two queues: (Active Node) [Output] [Working Set]
Starting with root:
( ) [] [A]
(A) [A] [B C D]
(B) [A B] [C D E F]
(C) [A B C] [D E F G]
(D) [A B C D] [E F G]
(E) [A B C D E] [F G]
(F) [A B C D E F] [G]
(G) [A B C D E F G] []
Done
A depth first search visits the lowest level (deepest children) of the tree first instead. There are two types of depth first search: pre-order and post-order. This just differentiates between when you add the node to the output (when you visit it vs leave it).
var rootNode = structure.getRoot();
var preOrder = new Array();
var postOrder = new Array();
function DepthFirst( rootNode ){
// Pre-order
preOrder[ preOrder.length ] = rootNode;
for( var child in rootNode ){
DepthFirst( child );
}
// Post-order
postOrder[ postOrder.length ] = rootNode;
}
Pre-order:
* A B E F C G D
Post-order:
* E F B G C D A
Say you have a tree as follows:
It may be a little confusing because E is both a child of A and F but it helps illustrate the depth in a depth first search. A depth first search searches the tree going as deep (hence the term depth) as it can first. So the traversal left to right would be A, B, D, F, E, C, G.
A breadth first search evaluates all the children first before proceeding to the children of the children. So the same tree would go A, B, C, E, D, F, G.
Hope this helps.
you can find everything on wiki:
BFS and DFS
this link can be useful too. if you want an implementation go to: c++ boost library: DFS
Here are a few links to check out:
Breadth-first search
BFS is an uninformed search method that aims to expand and examine all nodes of a graph or combination of sequences by systematically searching through every solution. In other words, it exhaustively searches the entire graph or sequence without considering the goal until it finds it.
Depth-first search
Formally, DFS is an uninformed search that progresses by expanding the first child node of the search tree that appears and thus going deeper and deeper until a goal node is found, or until it hits a node that has no children. Then the search backtracks, returning to the most recent node it hasn't finished exploring
Not only do they contain good explanations on how they are implemented in applications but also some algorithm pseudo code.
Breadth First Search/Depth First Search Animations
graph traversal with dfs and bfs.
in c++ and python.
Heres the idea in basics:
get a new queue ...initalize it with the root node .... loop through the entire queue and keep removing an item from the queue and printing it out (or saving it etc) and check if the same item has any children , if so push them onto the queue and continue in the loop until you traverse the entire segment(graph)...
snippet with 2 pointers.
void BFS(int v,struct Node **p)
{
struct Node *u;
visited[v-1] = TRUE;
printf("%d\t",v);
AddQueue(v);
while(IsEmpty() == FALSE)
{
v = DeleteQueue();
u = *(p+v-1);
while(u!=NULL)
{
if(visited(u->data -1) == FALSE)
{
AddQueue(u->data);
visited[u->data -1]=TRUE;
printf("%d\t",u->data);
}
u = u->next;
}
}
}
BFS and DFS are applicable to all kinds of graphs. I explain it for binary tree only. BFS visit each node top to bottom, left to right. For example for this:
1
/ \
7 9
\ / \
8 2 3
BFS gives us: 1 7 9 8 2 3. DFS visits depth of each branch first. Then, it comes back to its parents. You can follow this informal rule. First left child then right child then parent. But, you need to start from the depth of each branch. For example, here you start from 8, since there is no left child for 7. Then, you visit parent 7. Then, 1 parent of 7 will be visited. Then, you go to right branch. But, this time there is 2 as the left most child. So, you visit 2 (left child) then, right child 3 then, 9 their parents. So, DFS gives us 8 7 1 2 9 3. This is the implementation:
import java.util.ArrayList;
import java.util.List;
public class TreeTraverse {
static class Node{
Node(int data){
this.data = data;
this.left = null;
this.right = null;
this.visited = false;
}
int data;
Node left;
Node right;
boolean visited;
}
public static void main(String[] args) {
//The tree:
// 1
// / \
// 7 9
// \ / \
// 8 2 3
Node node1 = new Node(1);
Node node7 = new Node(7);
Node node9 = new Node(9);
Node node8 = new Node(8);
Node node2 = new Node(2);
Node node3 = new Node(3);
node1.left = node7;
node1.right = node9;
node7.right = node8;
node9.right = node3;
node9.left = node2;
System.out.println("DFS: ");
depthFirstSearch(node1);
System.out.println("\nBFS: ");
breadthFirstSearch(node1);
}
private static void depthFirstSearch(Node node){
if(node.left == null && node.right == null){
System.out.print(node.data+" ");
node.visited = true;
}else if(node.left == null || node.left.visited){
depthFirstSearch(node.right);
System.out.print(node.data+" ");
node.visited = true;
}else{
depthFirstSearch(node.left);
node.visited = true;
System.out.print(node.data+" ");
depthFirstSearch(node.right);
}
}
private static void breadthFirstSearch(Node node){
List<Node> al = new ArrayList<>();
al.add(node);
while(!al.isEmpty()){
node = al.get(0);
if(node.left != null){
int index = al.size();
al.add(index,node.left);
}
if(node.right != null){
int index = al.size();
al.add(index,node.right);
}
System.out.print(al.get(0).data+" ");
al.remove(0);
}
}
}
I hope it helps. If you want to clone the project, please visit: https://github.com/m-vahidalizadeh/foundations/blob/master/src/algorithms/TreeTraverse.java. I hope it helps.
First of all, BFS and DFS are two ways to implement binary tree traversal. Breadth First means level order traversal. Depth First has three ways to implemnt -- , , .
Preorder:
a. Start with root,
b. mark it visited,
c. go to left node
d. (b) - mark it visited
e. Repeat (c) till there is not any new left node remaining
(We are/might be at leaf node at this point,)
f. Is there any right node available? If yes, go to (a).
Level Order Traversal
Time Complexity
O(n)- Number of times each node is visited is 1 only, means total is n times.
Space Complexity-
Best Case: Tree only left nodes, is O(1)
Average Case: Perfect binary tree is example, n/2 number of nodes, O(n)

Resources