construct binary search tree from Post-order traversal in Java - java

I am implementing code to construct BST(binary search tree) from a given post-order traversal array following this algorithm. I do not get back the binary Search Tree back. I am getting something that makes no-sense. here is my code
public class BinaryTreemethods {
public static void main(String[] args) {
int[] preOrder = { 5, 3, 1, 4, 8, 6, 9 };
int[] inOrder = { 1, 3, 4, 5, 6, 8, 9 };
int[] postOrder = {1,4,3,8,6,9,5};
static int postIndex=postOrder.length-1;
Node postordertree= buildBinarytreefromPostOrder(postOrder, 0, postOrder.length-1);
System.out.println("pre order traversal of node from postorder reconstructed tree ");
printPreOrder(postordertree);
}
private static void printPreOrder(Node tree) {
if (tree != null) {
System.out.print(" " + tree.data);
printPreOrder(tree.left);
printPreOrder(tree.right);
}
}
//this just reconstructs BT from post-order traversal elements
public static Node buildBinarytreefromPostOrder(int[] post, int start, int end){
if (postIndex<start || start > end ){
return null;
}
Node root = new Node(post[postIndex]);
postIndex--;
if (end == start){
//System.out.println("called");
return root;
}
int i = 0;
for (i=end;i>=start;i--){
if (post[i]<root.data)
break;
}
// Use the index of element found in postorder to divide postorder array
// in two parts. Left subtree and right subtree
root.right=buildBinarytreefromPostOrder(post,i+1, postIndex);
root.left=buildBinarytreefromPostOrder(post,start,i);
//root.left=buildBinarytreefromPostOrder(post,start,i);
//root.right=buildBinarytreefromPostOrder(post,i+1, postIndex);
return root;
}
}
The output when I print in pre-order traversal is 5 9 6 8 3 4 which is not correct.
Any idea where I could be going wrong?
EDIT: After swapping the order of lines for root.right and root.left (commented out one were before),
the left tree is build correctly, but the right tree is not. The output I get is
5 3 1 4 9 6 8

As the root of each subtree you are taking postIndex which is global for the whole structure. You should take the last element of the subarray (end).
It should rather be like this
public static Node buildBinarytreefromPostOrder(int[] post, int start, int end)
{
if (end < start)
return null;
Node root = new Node(post[end]);
if (end == start)
return root;
int i;
for (i = end; i >= start; i--)
if (post[i] < root.data)
break;
root.left = buildBinarytreefromPostOrder(post, start, i);
root.right = buildBinarytreefromPostOrder(post, i + 1, end - 1);
return root;
}

Related

Binary tree breadth first search algorithm

In a binary tree BFS algorithm, can someone please help me understand why we do a height - 1 in the code below. I wrote this code but it never worked until I figured out online you need to do a height - 1.
public class BreadthFirstSearch {
public static int calculateHeightOfTree(Node root) {
if (root == null) {
return 0;
} else {
return 1 + Math.max(calculateHeightOfTree(root.leftNode), calculateHeightOfTree(root.rightNode));
}
}
public static void printDataAtAllLevels(Node root, int height) {
for (int i = 1; i <= height; i++) {
printDataAtGivenLevel(root, i);
}
}
public static void printDataAtGivenLevel(Node root, int height) {
if (root == null) {
return;
}
if (height == 1) {
System.out.println(root.data);
} else {
printDataAtGivenLevel(root.leftNode, height - 1);
printDataAtGivenLevel(root.rightNode, height - 1);
}
}
public static void main(String[] args) {
Node node = new Node(1);
node.leftNode = new Node(2);
node.rightNode = new Node(3);
node.leftNode.leftNode = new Node(4);
node.leftNode.rightNode = new Node(5);
System.out.println("Level order traversal of binary tree is ");
int height = calculateHeightOfTree(node);
System.out.println("HEIGHT: " + height);
printDataAtAllLevels(node, height);
}
Well, if you want to print the data of level n of the tree, that's equivalent to printing the data of level n-1 of the left and right sub-trees. Therefore, when you pass the left and right sub-trees to the recursive calls, you should request to print the data of level reduced by 1.
For example, since the root of the tree has level 1, the left and right children of the root have level 2.
So if you wish to print all the data of level 2 for the original tree, that's equivalent to printing the data of level 1 for the left and right sub-trees.
If you would not decrease height it would always be the same value in every (recursive) method call.
Therefore the recursion would not stop because height == 1 would always be false. It would only stop because root == null would be true, because you reached the end of a sub-tree. But in this case there would be no output, but only a return.
Because the height int printDataAtGivenLevel(Node root, int height) is the height relative to the root. So if you want to print level 2 from the root, you need to print level 1 from root.left and root.right.
So that you can print the height starting from the node with the lowest height to the node with the maximum height.
Honestly, when I read Binary tree breadth first search algorithm, I do not think about a series of depth-limited DFS traversals, but visiting nodes of a given level, and collecting the ones for the next level, rinse and repeat:
static void doStuff(Node root){
List<Node> current=new ArrayList<>();
current.add(root);
int level=0;
int total=0;
while(current.size()>0){
level++;
System.out.println("Level "+level+":");
List<Node> next=new ArrayList<>();
for(int i=0;i<current.size();i++){
Node node=current.get(i);
System.out.print(node.data+" ");
if(node.leftNode!=null)
next.add(node.leftNode);
if(node.rightNode!=null)
next.add(node.rightNode);
total++;
}
System.out.println();
current=next;
}
System.out.println(total+" nodes visited, from "+level+" levels");
}
Then it can be tricked into one list:
static void doStuff(Node root){
List<Node> nodes=new LinkedList<>();
nodes.add(root);
int level=0;
int total=0;
int current;
while((current=nodes.size())>0){
level++;
System.out.println("Level "+level+":");
while(current-->0){
Node node=nodes.removeFirst();
System.out.print(node.data+" ");
if(node.leftNode!=null)
nodes.add(node.leftNode);
if(node.rightNode!=null)
nodes.add(node.rightNode);
total++;
}
System.out.println();
}
System.out.println(total+" nodes visited, from "+level+" levels");
}

How to create a binary search tree that includes all numbers from 1 to n

Im trying to create a Binary search tree that includes all numbers from 1 to n. an example would be from 1 to 5 would be something like
root: 3
root.left: 2
root.left.left = 1
root.right = 4
root.right.right = 5
This tree happens to be not very balanced, but I would prefer a method that produces as balanced of a tree as possible.
I am trying to create my own data structure for this, so I basically just wrote a Node class:
private class BinaryNode{
int data;
BinaryNode left;
BinaryNode right;
BinaryNode parent;
}
And I planned on having that inside another class, which represents the tree itself. I am stuck finding a good way determine the left/right values appropriately to build the tree, any help is appreciated!
The data on the root node would be (n+1)/2; if you've got a subtree representing the range [i..j], the root of that subtree is (i+j)/2 (using integer arithmetic).
You can build the tree recursively using that fact:
static BinaryNode build(int i, int j) {
if (i > j) return null;
int mid = (i + j) / 2; // Assumes i >= 0.
BinaryNode node = new BinaryNode();
node.data = mid;
node.left = build(i, mid - 1);
if (node.left != null) node.left.parent = node;
node.right = build(mid + 1, j);
if (node.right != null) node.right.parent = node;
return node;
}
Then start the recursive call:
BinaryNode node = build(1, n);
It must be pointed out, however, that such a binary search tree (storing contiguous integers from 1 to n) is useless: you may as well simply use an array, and "search" it using an array index.
public void insert(int id){
Node newNode = new Node(id);
if(root==null){
root = newNode;
return;
}
Node current = root;
Node parent = null;
while(true){
parent = current;
if(id<current.data){
current = current.left;
if(current==null){
parent.left = newNode;
newNode.parent = parent;
return;
}
}else{
current = current.right;
if(current==null){
parent.right = newNode;
newNode.parent = parent;
return;
}
}
}
}
Without recursion insertion of 1 to n numbers.
public static void main(String arg[]){
Solution2 s = new Solution2();
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for(int i = 1;i <= n;i++){
s.insert(i);
}
}

Rewrite a C code in Java to construct full binary tree

I want to write a function to construct a full binary tree from a given preorder and postorder array. I found that link http://www.geeksforgeeks.org/full-and-complete-binary-tree-from-given-preorder-and-postorder-traversals/ which proposes the following C code :
struct node* constructTreeUtil (int pre[], int post[], int* preIndex,
int l, int h, int size)
{
// Base case
if (*preIndex >= size || l > h)
return NULL;
// The first node in preorder traversal is root. So take the node at
// preIndex from preorder and make it root, and increment preIndex
struct node* root = newNode ( pre[*preIndex] );
++*preIndex;
// If the current subarry has only one element, no need to recur
if (l == h)
return root;
// Search the next element of pre[] in post[]
int i;
for (i = l; i <= h; ++i)
if (pre[*preIndex] == post[i])
break;
// Use the index of element found in postorder to divide postorder array in
// two parts. Left subtree and right subtree
if (i <= h)
{
root->left = constructTreeUtil (pre, post, preIndex, l, i, size);
root->right = constructTreeUtil (pre, post, preIndex, i + 1, h, size);
}
return root;
}
// The main function to construct Full Binary Tree from given preorder and
// postorder traversals. This function mainly uses constructTreeUtil()
struct node *constructTree (int pre[], int post[], int size)
{
int preIndex = 0;
return constructTreeUtil (pre, post, &preIndex, 0, size - 1, size);
}
I tried to rewrite this code in Java. Here is my code :
private static TreeNode constructTree(int[] preorder, int[] postorder, Index index, int lowIndex, int highIndex){
// Base case
if (index.index >= preorder.length || lowIndex > highIndex){
return null;
}
// The first node in preorder traversal is root. So take the node at
// preIndex from preorder and make it root, and increment preIndex
TreeNode root = new TreeNode (preorder[lowIndex]);
index.index++;
// If the current subarry has only one element, no need to recur
if (lowIndex == highIndex){
return root;
}
// Search the next element of pre[] in post[]
int i = 0;
for (i = lowIndex; i <= highIndex; ++i)
if (preorder[i]== postorder[lowIndex])
break;
// Use the index of element found in postorder to divide postorder array in
// two parts. Left subtree and right subtree
if (i <= highIndex) {
root.left = constructTree(preorder, postorder, index, lowIndex, i);
root.right = constructTree(preorder, postorder, index, i + 1, highIndex);
}
return root;
}
//The main function to construct Full Binary Tree from given preorder and
//postorder traversals. This function mainly uses constructTreeUtil()
public static TreeNode constructTree (int preorder[], int postorder[]) {
return constructTree (preorder, postorder, new Index(), 0, preorder.length - 1);
}
But I got a continuous loop in the root node (it didn't pass to the other nodes which have to be its child). Can you help me please to see where is the error in my Java code?
I'm not really sure but I think that the error maybe comes from these lines :
int i = 0;
for (i = lowIndex; i <= highIndex; ++i)
if (preorder[i]== postorder[lowIndex])
break;
I didn't understand very well the correspond lines in the original C code. Especially in this part
Here are the bugs:
Line if (preorder[i]== postorder[lowIndex]) has two errors: the first is that you search in preorder instead of in postorder, and the second is that you use lowIndex instead of preIndex.
This line should be: if (preorder[index.index]== postorder[i])
Line TreeNode root = new TreeNode (preorder[lowIndex]); - lowIndex is used again instead of preIndex.
This line should be: TreeNode root = new TreeNode (preorder[index.index]);
Pay attention to the fact that this code would work only for full binary trees
Assuming that your code written in C works, then my guess is that for this part
// Search the next element of pre[] in post[]
int i = 0;
for (i = lowIndex; i <= highIndex; ++i)
if (preorder[i]== postorder[lowIndex])
break;
you'd want to use the same variables that you use in the C version. In this case, your if statement should be
if (preorder[index.index]== postorder[i])
First make your TreeNode into a class, since it is the java equivalent of a struct
public class TreeNode{
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val){
this.val = val;
}
}
Then make your TreeUtil class
public class TreeUtil{
private static TreeNode constructTree(int[] preorder, int[] postorder, int index, int lowIndex, int highIndex){
// Base case
if (index >= preorder.length || lowIndex > highIndex){
return null;
}
// The first node in preorder traversal is root. So take the node at
// preIndex from preorder and make it root, and increment preIndex
TreeNode root = new TreeNode (preorder[index]);
index++;
// If the current subarry has only one element, no need to recur
if (lowIndex == highIndex){
return root;
}
// Search the next element of pre[] in post[]
for (int i = lowIndex; i <= highIndex; i++)
if (preorder[index]== postorder[i]){
// Use the index of element found in postorder to divide postorder array in
// two parts. Left subtree and right subtree
root.left = constructTree(preorder, postorder, index, lowIndex, i);
root.right = constructTree(preorder, postorder, index, i + 1, highIndex);
break;
}
}
return root;
}
//The main function to construct Full Binary Tree from given preorder and
//postorder traversals. This function mainly uses constructTreeUtil()
public static TreeNode constructTree (int preorder[], int postorder[]){
return constructTree (preorder, postorder, 0, 0, preorder.length - 1);
}
}
Errors in your code were if (preorder[i]== postorder[lowIndex] and TreeNode root = new TreeNode (preorder[lowIndex]); as mentioned by aviad. I changed your code for you to be slightly less confusing. Using the Index is a great way to confuse yourself especially since an int will work fine. Also ++i increments before you run the loop and isn't conventionally used in java and java lets you declare variables a part of your loop definition so I changed that for loop to be more what your are looking for.

Java: Breadth-First-Traversal Order Over an Array

I wish to iterate over a sorted array in the order that a breadth first traversal would give if I put the array into a binary tree and performed a BFT on that (which is how I currently achieve this). Obviously this involves additional memory overhead since you need to build and store the array again in the binary tree. I know this should be similar to a binary search but I can't quite get the ordering right.
Here's how I currently achieve this:
BTree bst = sortedArrayToBST(array);
Queue<BTree> queue = new LinkedList<BTree>();
queue.add(bst);
while(!queue.isEmpty()) {
BTree node = queue.remove();
System.out.println(node.data);
if(node.left != null) queue.add(node.left);
if(node.right != null) queue.add(node.right);
}
Here's what I have currently (but this obviously gives the wrong ordering):
public void bstIterate(int[] array, int start, int end) {
if(array.length == 0) return;
int med = array.length /2;
System.out.println(array[med]);
bstIterate(array,start,mid);
bstIterate(array,mid+1,array.length);
}
Can this be done without extra memory overhead, or do I have to store the items in a stack, vector or queue, and if so, how and would it require less memory than a binary tree?
I'm not sure this is particularly efficient, but one possible solution is to pass a depth parameter to your bstIterate method and call it repeatedly with increasing depth until it returns no more results.
Something like this:
public static boolean bstIterate(int array[], int start, int end, int depth) {
if (end <= start)
return false;
else {
int mid = start + (end-start)/2;
if (depth == 0) {
System.out.println(array[mid]);
return true;
}
else {
boolean res1 = bstIterate(array, start, mid, depth-1);
boolean res2 = bstIterate(array, mid+1, end, depth-1);
return res1 || res2;
}
}
}
which you would call like this:
int depth = 0;
while (bstIterate(array, 0, array.length, depth))
depth++;
Given this array:
int array[] = {1, 3, 4, 7, 9, 13, 18, 23, 25, 30};
that produces this tree:
13
4 25
3 9 23 30
1 7 18
and this output:
13
4
25
3
9
23
30
1
7
18
Is that what you had in mind?
I hope your sortedArrayToBST method is building a balanced binary tree from the given array. In that case the method you tried to implement will mimic a DFS (Depth first search) iteration over a BST. But your implementation is buggy, a correct implementation will look like this:
void bstIterate(int[] array, int start, int end) {
if (start > end) return;
int mid = start + (end - start) / 2; //it should not be array.lenght/2 because we are not updating the array at any point
bstIterate(array, start, mid-1); // mid is already printed so we no longer need it
bstIterate(array, mid+1, end);
}
//Now Call the method from you main
bstIterate(array, 0, array.length-1); //it should be array.length-1, as it is the last index of last element of the array
But from the question title I understand you are looking for BFS traversal over a sorted array by assuming the array as balanced binary tree.
Lets say our sorted array is this {1, 2, 3, 4, 5, 6, 7}. In that case a balanced BST will look like this:
4
/ \
2 6
/ \ / \
1 3 5 7
The BFS traversal on the above tree should output as follows: 4 2 6 1 3 5 7
I wrote a quick C++ implementation for this which will do the job in O(n) complexity (hope you can easily convert it to java):
#include <stdio.h>
#include <queue>
using namespace std;
class Node {
public:
int start;
int end;
};
void BFSiterate(int *arr, int start, int end) {
queue<Node>que;
Node n;
n.start = start;
n.end = end;
que.push(n);
while(!que.empty()) {
n = que.front();
que.pop();
int mid = n.start + (n.end - n.start) / 2;
printf("%d\n", arr[mid]);
Node x;
x.start = n.start;
x.end = mid-1;
if (x.start<=x.end)
que.push(x); //left
x.start = mid+1;
x.end = n.end;
if (x.start<=x.end)
que.push(x); //right
}
}
int main() {
int arr[] = {1, 2, 3, 4, 5, 6, 7};
int len = sizeof(arr)/4;
BFSiterate(arr, 0, len-1);
return 0;
}

Using a recursive method to find the smallest element in a subtree given the root: what am I doing wrong here?

So I have a homework question where I'm supposed to use a recursive method to "find the minimum element within a subtree rooted at the specified node"
And then I'm given this as my starting point:
public TreeNode
{
int data;
TreeNode left;
TreeNode right;
}
and
/**
Finds the minimum value for the subtree that is
rooted at a given node
#param n The root of the subtree
#return The minimum value
PRECONDITION: n is not null.
*/
int min(TreeNode n)
{
// COMPLETE THE BODY OF THIS METHOD
}
Now, I've got a very basic driver program written to insert nodes into the tree and I've written my recursive method, but it seems to be counting up instead of down, here's my method:
int min(TreeNode n){
if(n.left != null) {
n = n.left;
min(n);
System.out.println("N is now " + n.value);
}
return n.value;
}
Output of my code:
Building tree with rootvalue 25
=================================
Inserted 11 to left of node 25
Inserted 15 to right of node 11
Inserted 16 to right of node 15
Inserted 23 to right of node 16
Inserted 79 to right of node 25
Inserted 5 to left of node 11
Inserted 4 to left of node 5
Inserted 2 to left of node 4
Root is 25
N is now 2
N is now 4
N is now 5
N is now 11
The minimum integer in the given nodes subtree is: 11
Can someone please explain to me why this doesn't work?
Note: this is all assuming you're in a Binary Search Tree, so returning the minimum element means returning the left-most element.
This means your recursive call is quite simple:
min(node):
if this node has a left node:
return min(node.left)
if this node does not have a left node:
return this node's value
The logic is that if we don't have another left node then we are the left-most node, so we are the minimum value.
Now, in Java:
int min(TreeNode n){
if (n.left == null)
return n.value;
return min(n.left); // n.left cannot be null here
}
Now to explain your results, consider how this method works. It calls the method on the next node (min(n.left)) before continuing. In your case you had a println after this recursive call. Therefore the println inside the recursive call went first. So your prints started at the bottom of the tree and worked their way back up. This explains the "reverse order" printing.
Your method then returned 11 as your result because (as another answer has explained) your n = n.left didn't affect any of your recursive sub-calls, only the one in the current function call. This means you returned the left node of the root, rather than the furthest left child.
I hope this makes sense. If you need clarification on anything leave a comment or something. Recursion can be quite tricky to get your head around at first.
The issue is that Java is call-by-value, not by reference -- although references are passed by value. But what that really means in this case is that the call to min(n) does not change what the variable n refers to -- it doesn't do anything at all. What you should probably be doing is return min(n).
public static void main(String[] args) throws IOException, NoSuchMethodException, InitializationError {
Logger.getRootLogger().addAppender(new ConsoleAppender(new SimpleLayout(), "System.out"));
Logger.getRootLogger().setLevel(Level.ALL);
TreeNode n1 = new TreeNode();
TreeNode n2 = new TreeNode();
TreeNode n3 = new TreeNode();
TreeNode n4 = new TreeNode();
TreeNode n5 = new TreeNode();
TreeNode n6 = new TreeNode();
n1.data = 110;
n1.left = n2;
n1.right = n3;
n2.data = 15;
n2.left = n4;
n2.right = null;
n3.data = 3;
n3.left = null;
n3.right = null;
n4.data = 4;
n4.left = null;
n4.right = n5;
n5.data = 12;
n5.left = n6;
n5.right = null;
n6.data = 19;
n6.left = null;
n6.right = null;
System.out.print("min=" + min(n1));
}
static public class TreeNode {
int data;
TreeNode left;
TreeNode right;
}
static int min(TreeNode n) {
return min(n, n.data);
}
static int min(TreeNode n, int min) {
System.out.println("N is now " + n.data);
int currentMin = min;
if (n.left != null && n.right != null) {
final int left = min(n.left);
final int right = min(n.right);
if (left < right) {
currentMin = left;
} else {
currentMin = right;
}
} else if (n.left != null) {
currentMin = min(n.left);
} else if (n.right != null) {
currentMin = min(n.right);
}
if (currentMin < min) {
return currentMin;
} else {
return min;
}
}
OUTPUT is:
N is now 110
N is now 15
N is now 4
N is now 12
N is now 19
N is now 3
min=3
You need to use some tree traversal algoritm, for checking every node of the tree. Also you need to store current finded minimum. Pass this minimum into recursive function. It is calling "accumulator".
The last statement in your method implementation returns the node n's value. As n starts with the root and is replaced by its left child (if exists) you always get the value of the root's left child.
The following code should do it:
int min(final Tree n){
int result;
if(n == null){
result = Integer.MAX_VALUE;
} else {
result = n.value;
final int leftResult = min(n.left);
if(leftResult < result){
result = leftResult;
}
final int rightResult = min(n.right);
if(rightResult < result){
result = rightResult;
}
}
return result;
}
Or you could use the Visitor pattern (you would need to make your tree Iterable then and pass the values to the Visitor one-by-one):
interface TreeVisitor {
void accept(int value);
}
class MinTreeVisistor implements TreeVisitor {
int min = Integer.MAX_VALUE;
#Override
public void accept(int value) {
if(value < this.min) {
this.min = value;
}
}
}

Categories

Resources