how to rebuild BST using {pre,in,post}order traversals results - algorithm

We know the pre-order, in-order and post-order traversals. What algorithm will reconstruct the BST?

Because it is BST, in-order can be sorted from pre-order or post-order <1>. Actually, either pre-order or post-order is needed only....
<1> if you know what the comparison function is
From pre-order and in-order, to construct a binary tree
BT createBT(int* preOrder, int* inOrder, int len)
{
int i;
BT tree;
if(len <= 0)
return NULL;
tree = new BTNode;
t->data = *preOrder;
for(i = 0; i < len; i++)
if(*(inOrder + i) == *preOrder)
break;
tree->left = createBT(preOrder + 1, inOrder, i);
tree->right = createBT(preOrder + i + 1, inOrder + i + 1, len - i - 1);
return tree;
}
The rationale behind this:
In pre-order, the first node is the root. Find the root in the in-order. Then the tree can be divided into left and right. Do it recursively.
Similar for post-order and in-order.

I personally found Dante's answer a little hard to follow. I worked my way through the solution and found it to be similar to the one posted here http://geeksforgeeks.org/?p=6633
Complexity is O(N^2).
Here's another approach for building a tree using post-order traversal: http://www.technicallyidle.com/2011/02/15/build-binary-search-tree-using-post-order-traversal-trace/
Hope this helps

For reconstruction of a binary tree either preorder+inorder or postorder+inorder is needed. As already pointed out for a BST we can reconstruct using either preorder or postorder as sorting either of them will give us the inorder.
You can use the following function which is modification of the code given by #brainydexter to reconstruct the tree without using the static variable:
struct node* buildTree(char in[],char pre[], int inStrt, int inEnd,int preIndex){
// start index > end index..base condition return NULL.
if(inStrt > inEnd)
return NULL;
// build the current node with the data at pre[preIndex].
struct node *tNode = newNode(pre[preIndex]);
// if all nodes are constructed return.
if(inStrt == inEnd)
return tNode;
// Else find the index of this node in Inorder traversal
int inIndex = search(in, inStrt, inEnd, tNode->data);
// Using index in Inorder traversal, construct left and right subtress
tNode->left = buildTree(in, pre, inStrt, inIndex-1,preIndex+1);
tNode->right = buildTree(in, pre, inIndex+1, inEnd,preIndex+inIndex+1);
return tNode;
}

Here is a Ruby recursive solution
def rebuild(preorder, inorder)
root = preorder.first
root_inorder = inorder.index root
return root unless root_inorder
root.left = rebuild(preorder[1, root_inorder], inorder[0...root_inorder])
root.right = rebuild(preorder[root_inorder+1..-1], inorder[root_inorder+1..-1])
root
end
And an example
class Node
attr_reader :val
attr_accessor :left, :right
def initialize(val)
#val = val
end
def ==(node)
node.val == val
end
def inspect
"val: #{val}, left: #{left && left.val || "-"}, right: #{right && right.val || "-"}"
end
end
inorder = [4, 7, 2, 5, 1, 3, 8, 6, 9].map{|v| Node.new v }
preorder = [1, 2, 4, 7, 5, 3, 6, 8, 9].map{|v| Node.new v }
tree = rebuild(preorder, inorder)
tree
# val: 1, left: 2, right: 3
tree.left
# val: 2, left: 4, right: 5
tree.left.left
# val: 4, left: -, right: 7

Related

Finding the mode in Binary Search Tree

I saw this question has been around on this site, but I would like to discuss one issue please about tracking prev value in the code below. Given the following solution for finding the Mode in binary search tree,
class Solution {
Integer prev = null;
int count = 1;
int max = 0;
public int[] findMode(TreeNode root) {
//this is expandable, but int [] array is not expandable
List<Integer> modes = new ArrayList();
traverse(root, modes);
int[] result = new int[modes.size()];
for (int i=0; i<modes.size(); i++){
result[i] = modes.get(i);
}
return result;
}
//In BST, do inorder since that way nodes will be sorted L < root < R
public void traverse(TreeNode root, List<Integer> modes){
if(root == null) return; //dont do anything
traverse(root.left, modes);
if(prev != null){
if(prev == root.val){
count ++;
} else{
count =1;
}
}
if(count > max){
max = count;
modes.clear(); //delete all previous modes as we find a new one
modes.add(root.val);
} else if(count == max) { // we find another mode that has same # of occurrences
modes.add(root.val);
}
prev = root.val;
traverse( root.right, modes);
}
}
Now, the prev variable is supposed to capture the previous node value so that when we enter to node's left child as the code show, we will immediately compare it to left child of that node. For example, if prev = 5, then once we go up to 10, the new prev is prev = root.val;, then we got to 15 the right child of 10. But we don't compare prev to 15, but to 10 as we immediately go left in the code once, so we compare prev = 10 to node.val in if(prev == root.val) line. We go from there for all other nodes.
Problem: Suppose the node that is immediately left to 30 is 25 and not 20, then the trick used in this solution won't work in this case, what do you think pleas?
The algorithm is performing an in-order tree traversal, which does this:
traverse the left subtree by recursively calling the in-order function.
access the data part of the current node.
traverse the right subtree by recursively calling the in-order function.
In a binary search tree, because of the order of the nodes, an in-order traversal is visiting the nodes in ascending sorted order.
I think this picture (courtesy Wikipedia) will help to explain what's happening:
In-order traversal will visit the nodes in this order:
A, B, C, D, E, F, G, H, I;
Now since we are visiting the nodes is ascending sorted order, duplicates will be grouped together. Therefore, we just need to compare the current node with the previous node to find duplicates.
In your first example tree, the nodes are visited in this order:
5, 10, 10, 12, 15, 15, 16, 18, 20, 20, 20, 20, 25, 28, 30, 32.
The mode is 20.
In your second example tree, the nodes are visited in this order:
5, 10, 10, 12, 15, 15, 16, 18, 20, 20, 20, 25, 30, 32.
The mode is 20.

Construct binary tree given its inorder and preorder traversals without recursion

Given inorder and preorder traversals of a tree, how the tree can be re-constructed in non-recursive manner.
For example:
Re-construct the following tree
1
2 3
4 5 6 7
8 9
given
inorder traversal: 4, 2, 5, 8, 1, 6, 3, 9, 7
preorder traversal: 1, 2, 4, 5, 8, 3, 6, 7, 9
Note: There are many references to recursive implementations. For example, one may refer Construct Tree from given Inorder and Preorder traversals. However intent here is to find non-recursive implementation.
Idea is to keep tree nodes in a stack from preorder traversal, till their counterpart is not found in inorder traversal. Once a counterpart is found, all children in the left sub-tree of the node must have been already visited.
Following is non-recursive Java implementation.
public TreeNode constructTree(int[] preOrder, int[] inOrder) {
if (preOrder.length == 0) {
return null;
}
int preOrderIndex = 0;
int inOrderIndex = 0;
ArrayDeque<TreeNode> stack = new ArrayDeque<>();
TreeNode root = new TreeNode(preOrder[0]);
stack.addFirst(root);
preOrderIndex++;
while (!stack.isEmpty()) {
TreeNode top = stack.peekFirst();
if (top.val == inOrder[inOrderIndex]) {
stack.pollFirst();
inOrderIndex++;
// if all the elements in inOrder have been visted, we are done
if (inOrderIndex == inOrder.length) {
break;
}
// Check if there are still some unvisited nodes in the left
// sub-tree of the top node in the stack
if (!stack.isEmpty()
&& stack.peekFirst().val == inOrder[inOrderIndex]) {
continue;
}
// As top node in stack, still has not encontered its counterpart
// in inOrder, so next element in preOrder must be right child of
// the removed node
TreeNode node = new TreeNode(preOrder[preOrderIndex]);
preOrderIndex++;
top.right = node;
stack.addFirst(node);
} else {
// Top node in the stack has not encountered its counterpart
// in inOrder, so next element in preOrder must be left child
// of this node
TreeNode node = new TreeNode(preOrder[preOrderIndex]);
preOrderIndex++;
top.left = node;
stack.addFirst(node);
}
}
return root;
}

How to keep track of depth in breadth first search?

I have a tree as input to the breadth first search and I want to know as the algorithm progresses at which level it is?
# Breadth First Search Implementation
graph = {
'A':['B','C','D'],
'B':['A'],
'C':['A','E','F'],
'D':['A','G','H'],
'E':['C'],
'F':['C'],
'G':['D'],
'H':['D']
}
def breadth_first_search(graph,source):
"""
This function is the Implementation of the breadth_first_search program
"""
# Mark each node as not visited
mark = {}
for item in graph.keys():
mark[item] = 0
queue, output = [],[]
# Initialize an empty queue with the source node and mark it as explored
queue.append(source)
mark[source] = 1
output.append(source)
# while queue is not empty
while queue:
# remove the first element of the queue and call it vertex
vertex = queue[0]
queue.pop(0)
# for each edge from the vertex do the following
for vrtx in graph[vertex]:
# If the vertex is unexplored
if mark[vrtx] == 0:
queue.append(vrtx) # mark it as explored
mark[vrtx] = 1 # and append it to the queue
output.append(vrtx) # fill the output vector
return output
print breadth_first_search(graph, 'A')
It takes tree as an input graph, what I want is, that at each iteration it should print out the current level which is being processed.
Actually, we don't need an extra queue to store the info on the current depth, nor do we need to add null to tell whether it's the end of current level. We just need to know how many nodes the current level contains, then we can deal with all the nodes in the same level, and increase the level by 1 after we are done processing all the nodes on the current level.
int level = 0;
Queue<Node> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()){
int level_size = queue.size();
while (level_size-- != 0) {
Node temp = queue.poll();
if (temp.right != null) queue.add(temp.right);
if (temp.left != null) queue.add(temp.left);
}
level++;
}
You don't need to use extra queue or do any complicated calculation to achieve what you want to do. This idea is very simple.
This does not use any extra space other than queue used for BFS.
The idea I am going to use is to add null at the end of each level. So the number of nulls you encountered +1 is the depth you are at. (of course after termination it is just level).
int level = 0;
Queue <Node> queue = new LinkedList<>();
queue.add(root);
queue.add(null);
while(!queue.isEmpty()){
Node temp = queue.poll();
if(temp == null){
level++;
queue.add(null);
if(queue.peek() == null) break;// You are encountering two consecutive `nulls` means, you visited all the nodes.
else continue;
}
if(temp.right != null)
queue.add(temp.right);
if(temp.left != null)
queue.add(temp.left);
}
Maintain a queue storing the depth of the corresponding node in BFS queue. Sample code for your information:
queue bfsQueue, depthQueue;
bfsQueue.push(firstNode);
depthQueue.push(0);
while (!bfsQueue.empty()) {
f = bfsQueue.front();
depth = depthQueue.front();
bfsQueue.pop(), depthQueue.pop();
for (every node adjacent to f) {
bfsQueue.push(node), depthQueue.push(depth+1);
}
}
This method is simple and naive, for O(1) extra space you may need the answer post by #stolen_leaves.
Try having a look at this post. It keeps track of the depth using the variable currentDepth
https://stackoverflow.com/a/16923440/3114945
For your implementation, keep track of the left most node and a variable for the depth. Whenever the left most node is popped from the queue, you know you hit a new level and you increment the depth.
So, your root is the leftMostNode at level 0. Then the left most child is the leftMostNode. As soon as you hit it, it becomes level 1. The left most child of this node is the next leftMostNode and so on.
With this Python code you can maintain the depth of each node from the root by increasing the depth only after you encounter a node of new depth in the queue.
queue = deque()
marked = set()
marked.add(root)
queue.append((root,0))
depth = 0
while queue:
r,d = queue.popleft()
if d > depth: # increase depth only when you encounter the first node in the next depth
depth += 1
for node in edges[r]:
if node not in marked:
marked.add(node)
queue.append((node,depth+1))
If your tree is perfectly ballanced (i.e. each node has the same number of children) there's actually a simple, elegant solution here with O(1) time complexity and O(1) space complexity. The main usecase where I find this helpful is in traversing a binary tree, though it's trivially adaptable to other tree sizes.
The key thing to realize here is that each level of a binary tree contains exactly double the quantity of nodes compared to the previous level. This allows us to calculate the total number of nodes in any tree given the tree's depth. For instance, consider the following tree:
This tree has a depth of 3 and 7 total nodes. We don't need to count the number of nodes to figure this out though. We can compute this in O(1) time with the formaula: 2^d - 1 = N, where d is the depth and N is the total number of nodes. (In a ternary tree this is 3^d - 1 = N, and in a tree where each node has K children this is K^d - 1 = N). So in this case, 2^3 - 1 = 7.
To keep track of depth while conducting a breadth first search, we simply need to reverse this calculation. Whereas the above formula allows us to solve for N given d, we actually want to solve for d given N. For instance, say we're evaluating the 5th node. To figure out what depth the 5th node is on, we take the following equation: 2^d - 1 = 5, and then simply solve for d, which is basic algebra:
If d turns out to be anything other than a whole number, just round up (the last node in a row is always a whole number). With that all in mind, I propose the following algorithm to identify the depth of any given node in a binary tree during breadth first traversal:
Let the variable visited equal 0.
Each time a node is visited, increment visited by 1.
Each time visited is incremented, calculate the node's depth as depth = round_up(log2(visited + 1))
You can also use a hash table to map each node to its depth level, though this does increase the space complexity to O(n). Here's a PHP implementation of this algorithm:
<?php
$tree = [
['A', [1,2]],
['B', [3,4]],
['C', [5,6]],
['D', [7,8]],
['E', [9,10]],
['F', [11,12]],
['G', [13,14]],
['H', []],
['I', []],
['J', []],
['K', []],
['L', []],
['M', []],
['N', []],
['O', []],
];
function bfs($tree) {
$queue = new SplQueue();
$queue->enqueue($tree[0]);
$visited = 0;
$depth = 0;
$result = [];
while ($queue->count()) {
$visited++;
$node = $queue->dequeue();
$depth = ceil(log($visited+1, 2));
$result[$depth][] = $node[0];
if (!empty($node[1])) {
foreach ($node[1] as $child) {
$queue->enqueue($tree[$child]);
}
}
}
print_r($result);
}
bfs($tree);
Which prints:
Array
(
[1] => Array
(
[0] => A
)
[2] => Array
(
[0] => B
[1] => C
)
[3] => Array
(
[0] => D
[1] => E
[2] => F
[3] => G
)
[4] => Array
(
[0] => H
[1] => I
[2] => J
[3] => K
[4] => L
[5] => M
[6] => N
[7] => O
)
)
Set a variable cnt and initialize it to the size of the queue cnt=queue.size(), Now decrement cnt each time you do a pop. When cnt gets to 0, increase the depth of your BFS and then set cnt=queue.size() again.
In Java it would be something like this.
The idea is to look at the parent to decide the depth.
//Maintain depth for every node based on its parent's depth
Map<Character,Integer> depthMap=new HashMap<>();
queue.add('A');
depthMap.add('A',0); //this is where you start your search
while(!queue.isEmpty())
{
Character parent=queue.remove();
List<Character> children=adjList.get(parent);
for(Character child :children)
{
if (child.isVisited() == false) {
child.visit(parent);
depthMap.add(child,depthMap.get(parent)+1);//parent's depth + 1
}
}
}
Use a dictionary to keep track of the level (distance from start) of each node when exploring the graph.
Example in Python:
from collections import deque
def bfs(graph, start):
queue = deque([start])
levels = {start: 0}
while queue:
vertex = queue.popleft()
for neighbour in graph[vertex]:
if neighbour in levels:
continue
queue.append(neighbour)
levels[neighbour] = levels[vertex] + 1
return levels
I write a simple and easy to read code in python.
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def dfs(self, root):
assert root is not None
queue = [root]
level = 0
while queue:
print(level, [n.val for n in queue if n is not None])
mark = len(queue)
for i in range(mark):
n = queue[i]
if n.left is not None:
queue.append(n.left)
if n.right is not None:
queue.append(n.right)
queue = queue[mark:]
level += 1
Usage,
# [3,9,20,null,null,15,7]
n3 = TreeNode(3)
n9 = TreeNode(9)
n20 = TreeNode(20)
n15 = TreeNode(15)
n7 = TreeNode(7)
n3.left = n9
n3.right = n20
n20.left = n15
n20.right = n7
DFS().dfs(n3)
Result
0 [3]
1 [9, 20]
2 [15, 7]
I don't see this method posted so far, so here's a simple one:
You can "attach" the level to the node. For e.g., in case of a tree, instead of the typical queue<TreeNode*>, use a queue<pair<TreeNode*,int>> and then push the pairs of {node,level}s into it. The root would be pushed in as, q.push({root,0}), its children as q.push({root->left,1}), q.push({root->right,1}) and so on...
We don't need to modify the input, append nulls or even (asymptotically speaking) use any extra space just to track the levels.

Build BST from Preorder

Like many newbies, my head blows up from recursion. I looked up a lot of answers/explanations on SO. but I am still unclear on the concept. (This is not homework, I am trying to relearn what I unlearned and recursion was never a string point)
Given a preorder traversal, construct a binary tree. With recursion, it has to be deceptively simple :) but I just can't get it.
I see that the order of the arr has to be in the order nodes are inserted. What bugs me is:
What if the node already has a left/right? How does this work?
How can the recursion insert nodes, in say the following preorder?
12, 10, 6, 13
15 is root, 5, 3 and left
How does 6 get inserted correctly as 10's left child?
12
10 13
6*
Here is the skeleton code:
main()
{
int[] arr = {};
//make the first node a root node.
node n = new node(arr[0]);
buildbst(n, arr, 0)
}
buildbst(node root, int[] arr, int i)
{
if (i == arr.length) return;
if (arr[i] < root.data)
root.left = new node (arr[i]);
else
root.right = new node(arr[i]);
buildbst(root.left, arr, i++);
buildbst(root.right, arr, i++);
}
EDIT:
I just realised, if I pass in the recursive call buildbst(root.left, arr+i, i++)
is that the right way? Or am I approaching this all wrong - a mish-mash of dynamic programming and recursion and divide and conquer...
It can't already have a left / right child. You call it for the root, which has no children to start. Then you call it for the left child and create children where appropriate and call the function for those children and so on. You never visit the left child again once you go right and you can't get to a node from a function called on its child (since there is no connection up the tree, except the recursion stack).
This is what should happen when given 12, 10, 6, 13:
Creates the root 12
Calls buildbst(node(12), arr, 1)
Create node(12).left = node(10)
Calls buildbst(node(10), arr, 2)
Create node(10).left = node(6)
Calls buildbst(node(6), arr, 3)
13 > 12, must be right child of 12, so do nothing
13 > 12, must be right child of 12, so do nothing
Create node(12).right = node(13)
Calls buildbst(node(13), arr, 3)
Oh look, no more elements, we're done.
The above is not what will happen with your code for 2 reasons:
Your code will only create either a left or a right child, not both (because of the if-else))
Your code doesn't have the must be right child of '12' check, which is a little complex
The below code should cover it.
node buildbst(int[] arr)
{
node n = new node(arr[0]);
// 9999999999 is meant to be > than the biggest element in your data
buildbst(n, arr, 1, 9999999999);
return node;
}
int buildbst(node current, int[] arr, int i, int biggestSoFar)
{
if (i == arr.length) return i;
// recurse left
if (arr[i] < current.data)
{
current.left = new node(arr[i++]);
i = buildbst(current.left, arr, i, current.data);
}
// recurse right
if (i < arr.length && arr[i] < biggestSoFar)
{
current.right = new node(arr[i++]);
i = buildbst(current.right, arr, i, biggestSoFar);
}
return i;
}
Explanation:
The purpose of biggestSoFar is to prevent:
15 15
/ /\
5 versus (the correct) 5 20
/ \ /
1 20 1
When recursing left from 15 for example, we need to stop processing elements as soon as we get an element > 15, which will happen when we get 20. Thus we pass current.data and stop processing elements if we get a bigger value.
When recursing right from 5 for example, we need to stop processing elements as soon as we get an element > 15, which will happen when we get 20. Thus we pass biggestSoFar and stop processing elements if we get a bigger value.

Pre-order to post-order traversal

If the pre-order traversal of a binary search tree is 6, 2, 1, 4, 3, 7, 10, 9, 11, how to get the post-order traversal?
You are given the pre-order traversal of the tree, which is constructed by doing: output, traverse left, traverse right.
As the post-order traversal comes from a BST, you can deduce the in-order traversal (traverse left, output, traverse right) from the post-order traversal by sorting the numbers. In your example, the in-order traversal is 1, 2, 3, 4, 6, 7, 9, 10, 11.
From two traversals we can then construct the original tree. Let's use a simpler example for this:
Pre-order: 2, 1, 4, 3
In-order: 1, 2, 3, 4
The pre-order traversal gives us the root of the tree as 2. The in-order traversal tells us 1 falls into the left sub-tree and 3, 4 falls into the right sub-tree. The structure of the left sub-tree is trivial as it contains a single element. The right sub-tree's pre-order traversal is deduced by taking the order of the elements in this sub-tree from the original pre-order traversal: 4, 3. From this we know the root of the right sub-tree is 4 and from the in-order traversal (3, 4) we know that 3 falls into the left sub-tree. Our final tree looks like this:
2
/ \
1 4
/
3
With the tree structure, we can get the post-order traversal by walking the tree: traverse left, traverse right, output. For this example, the post-order traversal is 1, 3, 4, 2.
To generalise the algorithm:
The first element in the pre-order traversal is the root of the tree. Elements less than the root form the left sub-tree. Elements greater than the root form the right sub-tree.
Find the structure of the left and right sub-trees using step 1 with a pre-order traversal that consists of the elements we worked out to be in that sub-tree placed in the order they appear in the original pre-order traversal.
Traverse the resulting tree in post-order to get the post-order traversal associated with the given pre-order traversal.
Using the above algorithm, the post-order traversal associated with the pre-order traversal in the question is: 1, 3, 4, 2, 9, 11, 10, 7, 6. Getting there is left as an exercise.
Pre-order = outputting the values of a binary tree in the order of the current node, then the left subtree, then the right subtree.
Post-order = outputting the values of a binary tree in the order of the left subtree, then the right subtree, the the current node.
In a binary search tree, the values of all nodes in the left subtree are less than the value of the current node; and alike for the right subtree. Hence if you know the start of a pre-order dump of a binary search tree (i.e. its root node's value), you can easily decompose the whole dump into the root node value, the values of the left subtree's nodes, and the values of the right subtree's nodes.
To output the tree in post-order, recursion and output reordering is applied. This task is left upon the reader.
Based on Ondrej Tucny's answer. Valid for BST only
example:
20
/ \
10 30
/\ \
6 15 35
Preorder = 20 10 6 15 30 35
Post = 6 15 10 35 30 20
For a BST, In Preorder traversal; first element of array is 20. This is the root of our tree. All numbers in array which are lesser than 20 form its left subtree and greater numbers form right subtree.
//N = number of nodes in BST (size of traversal array)
int post[N] = {0};
int i =0;
void PretoPost(int pre[],int l,int r){
if(l==r){post[i++] = pre[l]; return;}
//pre[l] is root
//Divide array in lesser numbers and greater numbers and then call this function on them recursively
for(int j=l+1;j<=r;j++)
if(pre[j]>pre[l])
break;
PretoPost(a,l+1,j-1); // add left node
PretoPost(a,j,r); //add right node
//root should go in the end
post[i++] = pre[l];
return;
}
Please correct me if there is any mistake.
you are given the pre-order traversal results. then put the values to a suitable binary search tree and just follow the post-order traversal algorithm for the obtained BST.
This is the code of preorder to postorder traversal in python.
I am constructing a tree so you can find any type of traversal
def postorder(root):
if root==None:
return
postorder(root.left)
print(root.data,end=" ")
postorder(root.right)
def preordertoposorder(a,n):
root=Node(a[0])
top=Node(0)
temp=Node(0)
temp=None
stack=[]
stack.append(root)
for i in range(1,len(a)):
while len(stack)!=0 and a[i]>stack[-1].data:
temp=stack.pop()
if temp!=None:
temp.right=Node(a[i])
stack.append(temp.right)
else:
stack[-1].left=Node(a[i])
stack.append(stack[-1].left)
return root
class Node:
def __init__(self,data):
self.data=data
self.left=None
self.right=None
a=[40,30,35,80,100]
n=5
root=preordertoposorder(a,n)
postorder(root)
# print(root.data)
# print(root.left.data)
# print(root.right.data)
# print(root.left.right.data)
# print(root.right.right.data)
If you have been given preorder and you want to convert it into postorder. Then you should remember that in a BST in order always give numbers in ascending order.Thus you have both Inorder as well as the preorder to construct a tree.
preorder: 6, 2, 1, 4, 3, 7, 10, 9, 11
inorder: 1, 2, 3, 4, 6, 7, 9, 10, 11
And its postorder: 1 3 4 2 9 11 10 7 6
I know this is old but there is a better solution.
We don't have to reconstruct a BST to get the post-order from the pre-order.
Here is a simple python code that does it recursively:
import itertools
def postorder(preorder):
if not preorder:
return []
else:
root = preorder[0]
left = list(itertools.takewhile(lambda x: x < root, preorder[1:]))
right = preorder[len(left) + 1:]
return postorder(left) + postorder(right) + [root]
if __name__ == '__main__':
preorder = [20, 10, 6, 15, 30, 35]
print(postorder(preorder))
Output:
[6, 15, 10, 35, 30, 20]
Explanation:
We know that we are in pre-order. This means that the root is at the index 0 of the list of the values in the BST. And we know that the elements following the root are:
first: the elements less than the root, which belong to the left subtree of the root
second: the elements greater than the root, which belong to the right subtree of the root
We then just call recursively the function on both subtrees (which still are in pre-order) and then chain left + right + root (which is the post-order).
Here pre-order traversal of a binary search tree is given in array.
So the 1st element of pre-order array will root of BST.We will find the left part of BST and right part of BST.All the element in pre-order array is lesser than root will be left node and All the element in pre-order array is greater then root will be right node.
#include <bits/stdc++.h>
using namespace std;
int arr[1002];
int no_ans = 0;
int n = 1000;
int ans[1002] ;
int k = 0;
int find_ind(int l,int r,int x){
int index = -1;
for(int i = l;i<=r;i++){
if(x<arr[i]){
index = i;
break;
}
}
if(index == -1)return index;
for(int i =l+1;i<index;i++){
if(arr[i] > x){
no_ans = 1;
return index;
}
}
for(int i = index;i<=r;i++){
if(arr[i]<x){
no_ans = 1;
return index;
}
}
return index;
}
void postorder(int l ,int r){
if(l < 0 || r >= n || l >r ) return;
ans[k++] = arr[l];
if(l==r) return;
int index = find_ind(l+1,r,arr[l]);
if(no_ans){
return;
}
if(index!=-1){
postorder(index,r);
postorder(l+1,index-1);
}
else{
postorder(l+1,r);
}
}
int main(void){
int t;
scanf("%d",&t);
while(t--){
no_ans = 0;
int n ;
scanf("%d",&n);
for(int i = 0;i<n;i++){
cin>>arr[i];
}
postorder(0,n-1);
if(no_ans){
cout<<"NO"<<endl;
}
else{
for(int i =n-1;i>=0;i--){
cout<<ans[i]<<" ";
}
cout<<endl;
}
}
return 0;
}
As we Know preOrder follow parent, left, right series.
In order to construct tree we need to follow few basic steps-:
your question consist of series 6, 2,1,4,3,7,10,9,11
points-:
First number of series will be root(parent) i.e 6
2.Find the number which is greater than 6 so in this series 7 is first greater number in this series so right node will be starting from here and left to this number(7) is your left subtrees.
6
/ \
2 7
/ \ \
1 4 10
/ / \
3 9 11
3.same way follow the basic rule of BST i.e left,root,right
the series of post order will be L, R, N i.e. 1,3,4,2,9,11,10,7,6
Here is full code )
class Tree:
def __init__(self, data = None):
self.left = None
self.right = None
self.data = data
def add(self, data):
if self.data is None:
self.data = data
else:
if data < self.data:
if self.left is None:
self.left = Tree(data)
else:
self.left.add(data)
elif data > self.data:
if self.right is None:
self.right = Tree(data)
else:
self.right.add(data)
def inOrder(self):
if self.data:
if self.left is not None:
self.left.inOrder()
print(self.data)
if self.right is not None:
self.right.inOrder()
def postOrder(self):
if self.data:
if self.left is not None:
self.left.postOrder()
if self.right is not None:
self.right.postOrder()
print(self.data)
def preOrder(self):
if self.data:
print(self.data)
if self.left is not None:
self.left.preOrder()
if self.right is not None:
self.right.preOrder()
arr = [6, 2, 1, 4, 3, 7, 10, 9, 11]
root = Tree()
for i in range(len(arr)):
root.add(arr[i])
print(root.inOrder())
Since, it is a binary search tree, the inorder traversal will be always be the sorted elements. (left < root < right)
so, you can easily write its in-order traversal results first, which is : 1,2,3,4,6,7,9,10,11
given Pre-order : 6, 2, 1, 4, 3, 7, 10, 9, 11
In-order : left, root, right
Pre-order : root, left, right
Post-order : left, right, root
now, we got from pre-order, that root is 6.
now, using in-order and pre-order results:
Step 1:
6
/ \
/ \
/ \
/ \
{1,2,3,4} {7,9,10,11}
Step 2: next root is, using in-order traversal, 2:
6
/ \
/ \
/ \
/ \
2 {7,9,10,11}
/ \
/ \
/ \
1 {3,4}
Step 3: Similarly, next root is 4:
6
/ \
/ \
/ \
/ \
2 {7,9,10,11}
/ \
/ \
/ \
1 4
/
3
Step 4: next root is 3, but no other element is remaining to be fit in the child tree for "3". Considering next root as 7 now,
6
/ \
/ \
/ \
/ \
2 7
/ \ \
/ \ {9,10,11}
/ \
1 4
/
3
Step 5: Next root is 10 :
6
/ \
/ \
/ \
/ \
2 7
/ \ \
/ \ 10
/ \ / \
1 4 9 11
/
3
This is how, you can construct a tree, and finally find its post-order traversal, which is : 1, 3, 4, 2, 9, 11, 10, 7, 6

Resources