Why do I need to push the right node before the left node during iterative solution to pre-order traversal when it's supposed to be left before right? - binary-tree

To solve this leetcode question :
Binary tree pre order traversal
It is good to remember that pre-order traversal traverses a tree in the order of
root->left->right.
In light of this, if I write an iterative solution to the problem above following the order of insertion of root, left and right, my solution does not pass all the hidden test cases.
To understand this, below is the code that does not pass all the hidden test cases:
public List<Integer> preorderTraversal(TreeNode root) {
//preOrder means root comes before other traversals therefore root,left,right
List<Integer> finalListToReturn = new ArrayList();
if(root == null)
return finalListToReturn;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root); //add root first
while(!stack.isEmpty()){
TreeNode node = stack.pop();
finalListToReturn.add(node.val); //add to list
//left must be traversed before the right,this is the natural order for preOrder
if(node.left != null)
stack.push(node.left);
if(node.right != null)
stack.push(node.right);
}
return finalListToReturn;
}
but the above code will not pass all hidden testcases when I submit.
However, if i traverse right node before left, all testcases pass, why is that so ?
For context,this is the snippet that passes all hidden test cases when submited.
public List<Integer> preorderTraversal(TreeNode root) {
//preOrder means root comes before other traversals therefore root,left,right
List<Integer> finalListToReturn = new ArrayList();
if(root == null)
return finalListToReturn;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root); //add root first
while(!stack.isEmpty()){
TreeNode node = stack.pop();
finalListToReturn.add(node.val); //add to list
//once right is traversed first before left, then every test case passes,why is that so?
if(node.right != null)
stack.push(node.right);
if(node.left != null)
stack.push(node.left);
}
return finalListToReturn;
}
Why is it that the first code snippet which traverses a binary search tree in the right pre-order route(root->left->right) rather does not pass all test cases but when the same code is tweaked to traverse in the order of (root->right->left) in the second snippet,all test cases pass? Can someone explain why?

So basically, if you look carefully, we are using a stack.
Observe the while loop we are using critically and you'll realize that we do pop(ie return the item at the top), and in this case, a Stack follows the LIFO principle, that is , the last element in,becomes the first element to come out during a pop.
Now after we add our node.val to finalListToReturn inside the while loop, if we add the left element first and then push the right element, what it means is that , during the next iteration, the last element that entered, the right element, will be popped first since a stack follows LIFO.
Obviously, we don't want that, so we will rather push the right element first and then the left element. Now during the next pop, the left element will pop first before the right, which is what we were looking for originally.
Thus, our final code should be exactly like the second snippet above:
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> finalListToReturn = new ArrayList();
if(root == null)
return finalListToReturn;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
finalListToReturn.add(node.val);
if(node.right != null)
stack.push(node.right);
if(node.left != null)
stack.push(node.left);
}
return finalListToReturn;
}

Related

Comparision of iterative pre-order solutions

The most common solution to iterative pre-order tree traversal is as follows :-
1) Create an empty stack nodeStack and push root node to stack.
2) Do following while nodeStack is not empty.
….a) Pop an item from stack and print it.
….b) Push right child of popped item to stack ….c) Push left child of popped item to stack
Source geeksforgeeks
However I was thinking from the perspective of converting the recursive solution to iterative and came up with the following code :-
private static void preorder(Node root) {
Stack<Node> s = new Stack<Node>();
if(root != null){
System.out.println(root.data);
s.push(root);
}
while(!s.isEmpty()){
if(root.left != null){
root = root.left;
System.out.println(root.data);
s.push(root);
}
else{
Node p = s.pop();
if(p.right != null){
root = p.right;
System.out.println(root.data);
s.push(root);
}
}
}
}
I was wondering which is a better solution and why ?
If we go by the recursive solution the second implementation looks like a better solution , please correct me if I am wrong.

is wikipedia iterative postorder tree traversal pseudo code wrong?

Here is the pseudo code that wikipedia gives for iterative postorder tree traversal.
iterativePostorder(node)
parentStack = empty stack
lastnodevisited = null
while (not parentStack.isEmpty() or node ≠ null)
if (node ≠ null)
parentStack.push(node)
node = node.left
else
peeknode = parentStack.peek()
if (peeknode.right ≠ null and lastnodevisited ≠ peeknode.right)
/* if right child exists AND traversing node from left child, move right */
node = peeknode.right
else
visit(peeknode)
lastnodevisited = parentStack.pop()
It is pretty straight forward, and I have implemented it in Java. But it does not work, the problem is that every time it visits the most left leaf and return to its parent, it will add that left leaf again into the stack in next iteration. This causes an infinite loop. Is my method incorrect or the wikipedia version is wrong?
public static List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) return res;
Stack<TreeNode> s = new Stack<TreeNode>();
TreeNode lastVisitedNode = null;
TreeNode curr = root;
int i = 0;
while (curr != null || !s.isEmpty()) {
if (curr != null) {
System.out.println("push " + curr.val);
s.push(curr);
curr = curr.left;
} else {
curr = s.peek();
if (curr.right != null && lastVisitedNode != curr.right) {
curr = curr.right;
} else {
res.add(curr.val);
System.out.println("pop " + curr.val);
lastVisitedNode = s.pop();
}
}
System.out.println(s);
System.out.println(res);
if (i>8) break;
else i++;
}
return res;
}
The wikipedia version is wrong for the exact same reason as you've explained it.
Here is a probably better pseudo-code, from geeksforgeeks
1.1 Create an empty stack
2.1 Do following while root is not NULL
a) Push root's right child and then root to stack.
b) Set root as root's left child.
2.2 Pop an item from stack and set it as root.
a) If the popped item has a right child and the right child
is at top of stack, then remove the right child from stack,
push the root back and set root as root's right child.
b) Else print root's data and set root as NULL.
2.3 Repeat steps 2.1 and 2.2 while stack is not empty.
You will have to add extra code to check if the node right child is null in 2.1.a though.
The wikipedia pseudocode is not wrong. They use two different variables: node and peekNode, while you only use curr for both. Node == null refers to the case when there is no more of a left branch left to explore, so we can stop pushing and instead investigate the next element in the stack. You can either revert to using two different variables, or you make the following fix in your code:
Since you reassign curr to a non-null value everytime you investigate the stack, you need to reset curr to null after you visit your node. (Because the state that still no more left branch left to explore is still unchanged).
The wikipedia pseudocode doesn't have to do this because their node value remains null.
Here is my code which gives a perfect answer:
var currentNode = this.root()
var previousNode = null
while(!nodeStack.isEmpty() || currentNode) {
// If there is a node on which the recursive call is made, we have a subtree to explore. If this is null, we have to backtrack and do a callback.
if (currentNode) {
nodeStack.push(currentNode)
previousNode = currentNode
currentNode = currentNode.leftChild
} else {
currentNode = nodeStack.peek()
if (currentNode.rightChild && previousNode != currentNode.rightChild) {
currentNode = currentNode.rightChild
} else {
callback(currentNode)
currentNode = null
previousNode = nodeStack.pop()
}
}
}

How binary search tree is created?

Suppose i am having an array say
1 5 4 6 8 9 10 22 17 7 9 3
I want to create a binary search tree from this array. I need algorithm to understand that.
I have read rest other things related to BST like inorder traversal preorder postorder, tree walk, insertion deletion etc
Book has not provided how to create BST. Need help here
if you do not care about the tree being balanced it is simple:
put the first element of the tree as the head.
iterate over the array. if an element is bigger than the node take a left(repeat the step for the left child) otherwise take a right(repeat the step for the right child).
if the left/right child is a null insert your new value there.
guaranteed to produce a binary search tree - just not a balanced one.
Firstly, you should choose a root node for your BST. Once you have chosen a root node, it is already easy to construct a BST taking into consideration the fact that: left children are less than the parent node and all right children are greater than the parent node.
private Node root;
public void insert(int val) {
if (root == null) {
root = new Node(val);
} else {
insertHelper(root, val);
}
}
private void insertHelper(Node node, int val) {
if (val < node.val) {
if (node.left == null) {
node.left = new Node(val);
} else {
insertHelper(node.left, val);
}
} else if (node.val < val) {
if (node.right == null) {
node.right = new Node(val);
} else {
insertHelper(node.right, val);
}
}
}
If the given array is sorted, you can do the following:
Take the middle element of the array and make it the root of the tree
Take the left sub-array and make it the left sub-tree of the root recursively
Take the right sub-array and make it the right sub-tree of the root recursively
Otherwise you can always sort the array before applying the procedure
struct node* construct(int arr[], int start, int end)
{
if(start>end)
return;
else if (start==end)
{
/*assuming we have a function newNode(int) which creates a new BST Node*/
node* Node = newNode(arr[start]);
return Node;
}
int mid = (start+end)/2;
node* root = newNode(arr[mid]);
root->left = construct(arr,start,mid-1);
root->right = construct(arr,mid+1,end);
return root;
}

BST to LinkList and back to same BST

Since I could not find anything useful so I am here to ask my question:
How can we convert the BST to a In-order linklist, and back to "same" BST, without using any extra space.
What I have tried so far (still doing though): I tried Morris Traversal to link up to the next in-order successor,
but it is not able to connect for all the nodes, only working for the left subtree, and right subtree, not for the actual root of the tree.
Please suggest how can I convert Tree to Linked List and back to Same tree...
To store a tree in lists - you need at least two lists: one for pre-order traversal, and the other for in-order traversal.
Luckily - since the tree is a BST, the in-order traversal is just the sorted list.
So, you can store the pre-order traversal (You can try doing it in-place) and by sorting the elements in re-construction, you can get the in-order traversal.
This post discusses how to reconstruct a tree from the inorder and pre-order traversals of it.
Binary Search Tree to List:
subTreeToList(node)
if (node.hasLeft()) then subTreeToList(node.left, list)
list.add(node.Value)
if (node.hasRight()) subTreeToList(node.right, list)
end if
subTreeToList end
treeToList(tree)
subTreeToList(tree.root)
treeToList end
list <- new List()
treeToList(tree)
You need to implement the idea above into your solution, if you are working with object-oriented technologies, then list and trees should be data members, otherwise they should be passed to the functions as references.
You can build back your tree knowing that insertion in the tree looks like this:
Insert(tree, value)
if (tree.root is null) then
tree.createRoot(value)
else
node <- tree.root
while (((node.value < value) and (node.hasRight())) or ((node.value > value) and (node.hasLeft())))
if ((node.value < value) and (node.hasRight())) then node <- node.right()
else node <- node.left()
end if
while end
if (node.value > value) then node.createLeft(value)
else node.createRight(value)
end if
end if
insert end
You just have to traverse your list sequentially and call the function implemented based on my pseudo-code above. Good luck with your homework.
I think I found the solution myself: below is the complete Java implementation
The logic + pseudo Code is as below
[1] Find the left most node in the tree, that will be the head of the LinkList, store it in the class
Node HeadOfList = null;
findTheHeadOfInorderList (Node root)
{
Node curr = root;
while(curr.left != null)
curr = curr.left;
HeadOfList = curr; // Curr will hold the head of the list
}
[2] Do the reverse - inorder traversal of the tree to convert it to a LL on right pointer, and make sure the left pointer is always pointing to the parent of the node.
updateInorderSuccessor(Node root, Node inorderNext, Node parent)
{
if(root != null)
//Recursively call with the right child
updateInorderSuccessor(root.right, inorderNext, root);
// Update the in-order successor in right pointer
root.right = inorderNext;
inorderNext = root;
//Recursively call with the left child
updateInorderSuccessor(root.left, inorderNext, root);
// Update the parent in left pointer
root.left = parent;
}
}
[3] To convert it back :
Traverse the list and find the node with left pointer as null,
Make it the root, break the link of this root in the linklist and also from its children...
Now the link list is broken into two parts one for left Subtree and one for right subtree,
recursively find the roots in these two list and make them the left and right child, Please refer the function restoreBST()
Node restoreBST(Node head)
{
if(head == null || (head.left == null && head.right == null)) return root;
Node prev, root, right, curr;
curr = head;
// Traverse the list and find the node with left as null
while(curr != null)
{
if(curr.left == null)
{
// Found the root of this tree
root = curr;
// Save the head of the right list
right = curr.right;
// Detach the children of the root just found, these will be updated later as a part of the recursive solution
detachChildren(curr, head);
break;
}
prev = curr;
curr = curr.right;
}
// By now the root is found and the children of the root are detached from it.
// Now disconnect the right pointer based connection in the list for the root node, so that list is broken in to two list, one for left subtree and one for right subtree
prev.right = null;
root.right = null;
// Recursively call for left and right subtree
root.left = restoreBST(head);
root.right = restoreBST(right);
//now root points to its proper children, lets return the root
return root;
}
Logic to detach the children is simple : Iterate through the list and look for the nodes with left pointer equal to root.
private void detachChildren(AvlNode root, AvlNode head) {
AvlNode curr = head;
while(curr != null)
{
if(curr.left == root)
{
curr.left = null;
}
curr = curr.right;
}
}
Here is a recursive solution for BST to LL, hope you find it useful.
Node BSTtoLL(BST root) {
if(null == root) return null;
Node l = BSTtoLL(root.left);
Node r = BSTtoLL(root.right);
Node l1 = null;
if(null != l) {
l1 = l;
while(null != l.left) { l = l.left; }
l.left = root;
l.right = null;
}
if(null != r) {
root.left = r;
root.right = null;
}
if(null != l1) return l1;
return root;
}

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