Something wrong with my Invert tree or BFS traverse? - java

I had already attached two tree to test, but the answer below is weird.
Input are two trees and to check if they are inverted version. So i wrote a invert function and a BFS traverse to store the tree node into a String, through comparing the two string to check if they are inverted version.
The first tree is
5
15
14
9
6
3
1
The second tree is:
5
15
14
9
6
3
1
5
14
15
3
6
9
1
No, not mirror imagines
Process finished with exit code 0
public class CheckMirrorTree{
public static void main(String[] args) {
// add the first tree
TreeNode root = new TreeNode(5);
root.left = new TreeNode(15);
root.right = new TreeNode(14);
TreeNode rightChild = root.right;
TreeNode leftChild = root.left;
rightChild.left = new TreeNode(3);
rightChild.left.right = new TreeNode(1);
leftChild.right = new TreeNode(6);
leftChild.left = new TreeNode(9);
System.out.println("The first tree is");
String root1 = traverse(root);
// add the second tree
System.out.println("The second tree is:");
TreeNode secondRoot = new TreeNode(5);
secondRoot.right = new TreeNode(15);
secondRoot.left = new TreeNode(14);
TreeNode secondRightChild = secondRoot.right;
TreeNode secondLeftChild = secondRoot.left;
secondRightChild.left = new TreeNode(6);
secondRightChild.right = new TreeNode(9);
secondLeftChild.right = new TreeNode(3);
secondLeftChild.right.left = new TreeNode(1);
String root2 = traverse(secondRoot);
if (root1 == root2){
System.out.println("Yes, mirror images");
}else {
System.out.println("No, not mirror imagines");
}
}
static Deque<TreeNode> queue = new ArrayDeque();
static List<Integer> result = new LinkedList();
static Deque<TreeNode> invertQueue = new ArrayDeque();
static private TreeNode invertTree(TreeNode root) {
invertQueue.add(root);
TreeNode reserve = root;
while (!invertQueue.isEmpty()) {
if (root.left != null || root.right != null) {
invertQueue.poll();
TreeNode temp = root.right;
root.right = root.left;
root.left = temp;
if (root.left != null)
invertQueue.add(root.left);
if (root.right != null)
invertQueue.add(root.right);
}
root = invertQueue.poll();
}
return reserve;
}
static private String traverse (TreeNode root){ // Each child of a tree is a root of its subtree.
queue.add(root);
helper(root);
// print out the tree
String res = "";
for (int i : result) {
System.out.println(i);
res += i;
}
return res;
}
static private void helper(TreeNode root) {
while (!queue.isEmpty()) {
if(root.left != null || root.right != null) {
TreeNode temp = queue.poll();
result.add(temp.val);
if (root.left != null)
queue.add(root.left);
if (root.right != null)
queue.add(root.right);
helper(queue.peek());
}
// deal with the ending nodes
if (root.left == null && root.right == null) {
if (queue.size() == 0) {
result.add(root.val);
return;
}
result.add(queue.poll().val);
root = queue.peek();
}
}
}
}

root1 == root2
is not how you check if two strings are equal. Try:
root1.equals(root2);
Then your if statement should be entered and something will be printed.
Since nothing else is getting printed I would suggest posting the traverse method since that's probably where the program is exiting early.

Related

Why do we need a temporary node while inserting values in a node in Linked list?

I was creating a binary tree using linked list in java, which inserts the value according to the height of the tree i.e if the height is even or odd. I wrote a code which initially had no temporary node for insertion of values to the root node and further left or right subtree nodes. But when I displayed this tree, output had no root node as if it was overwritten.
Below is the code of my initial program. Concentrate on public void insert_node() function.
import java.util.Scanner;
public class binary_tree {
private TreeNode root;
private int height = 0;
public static class TreeNode {
private int data;
private TreeNode left;
private TreeNode right;
public TreeNode(int user_input) {
this.data = user_input;
}
}
public void insertNode(TreeNode newnode) { // HERE....I have used only root.
if (root == null) {
root = newnode;
height += 1;
return;
}
if (height % 2 != 0) {
System.out.println(height);
while (root.left != null) {
root = root.left;
}
root.left = newnode;
height += 1;
return;
}
while (root.right != null) {
root = root.right;
}
root.right = newnode;
height += 1;
}
public void display(TreeNode rootnode) {
TreeNode temp = rootnode;
if (temp == null)
System.out.println("Tree Empty !!!");
else {
System.out.println("press 1 for LEFT SUBTREE \npress 2 for RIGHT SUBTREE.");
Scanner sc = new Scanner(System.in);
int ch = sc.nextInt();
while (temp != null) {
System.out.println(temp.data + " $");
if (ch == 1)
temp = temp.left;
else
temp = temp.right;
}
}
System.out.println("Height of the tree = " + height);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
binary_tree bt = new binary_tree();
TreeNode newNode = new TreeNode(50);
bt.insertNode(newNode);
TreeNode newNode2 = new TreeNode(10);
bt.insertNode(newNode2);
TreeNode newNode3 = new TreeNode(100);
bt.insertNode(newNode3);
TreeNode newNode4 = new TreeNode(5);
bt.insertNode(newNode4);
TreeNode newNode5 = new TreeNode(1000);
bt.insertNode(newNode5);
bt.display(bt.root);
}
}
Output
press 1 for LEFT SUBTREE
press 2 for RIGHT SUBTREE.
3
10 $
1000 $
Height of the tree = 5
You can see in the above code, that the 50 $ is missing which was supposed to be the root node.
Now, if I use a temporary node which in my case is current_node then this root node sustains somehow. See in the code below.
import java.util.Scanner;
public class binary_tree {
private TreeNode root;
private int height = 0;
public static class TreeNode {
private int data;
private TreeNode left;
private TreeNode right;
public TreeNode(int user_input) {
this.data = user_input;
}
}
public void insertNode(TreeNode newnode) {
TreeNode current_node = root; //THIS IS THE TEMPORARY NODE
if (current_node == null) {
root = newnode;
height += 1;
return;
}
if (height % 2 != 0) {
System.out.println(height);
while (current_node.left != null) {
current_node = current_node.left;
}
current_node.left = newnode;
height += 1;
return;
}
while (current_node.right != null) {
current_node = current_node.right;
}
current_node.right = newnode;
height += 1;
}
public void display(TreeNode rootnode) {
TreeNode temp = rootnode;
if (temp == null)
System.out.println("Tree Empty !!!");
else {
System.out.println("press 1 for LEFT SUBTREE \npress 2 for RIGHT SUBTREE.");
Scanner sc = new Scanner(System.in);
int ch = sc.nextInt();
while (temp != null) {
System.out.println(temp.data + " $");
if (ch == 1)
temp = temp.left;
else
temp = temp.right;
}
}
System.out.println("Height of the tree = " + height);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
binary_tree bt = new binary_tree();
TreeNode newNode = new TreeNode(50);
bt.insertNode(newNode);
TreeNode newNode2 = new TreeNode(10);
bt.insertNode(newNode2);
TreeNode newNode3 = new TreeNode(100);
bt.insertNode(newNode3);
TreeNode newNode4 = new TreeNode(5);
bt.insertNode(newNode4);
TreeNode newNode5 = new TreeNode(1000);
bt.insertNode(newNode5);
bt.display(bt.root);
}
}
Output
press 1 for LEFT SUBTREE
press 2 for RIGHT SUBTREE.
3
50 $
100 $
1000 $
Height of the tree = 5
So anyone who can tell me what's happening here? What difference does that current_node is making?
Why do we need a temporary node while inserting values in a node in Linked list?
Because you are traversing to the leaves of the tree here:
while (current_node.left != null) {
current_node = current_node.left;
}
current_node.left = newnode;
height += 1;
In these lines of code, you are trying to find the leftmost leaf so as to insert newnode, right? You want to use a variable to keep track of which node you are currently on, and "go left" by doing someVariable = someVariable.left;.
You could use root to keep track of where you are at, but root already has a purpose - to record the root of the tree! If you did root = root.left;, you are making the left node of the original root be the new root! Say your tree was:
50
/ \
10 100
Doing root = root.left deletes most of it:
10
This is problematic because this means your tree essentially "forgets" about a part of the tree. Technically, The 50 and 100 nodes still exists and 50 is still connected to 10, but your binary_tree object doesn't have access to it anymore. The only point of access it has is root, which you have now set to the node 10.
What actually happens in your program is: it correctly inserts 50, 10, and 100, then when adding 5, tries to traverse down the left subtree. This makes the root "10", and adding 5 becomes:
10
/
5
It then adds 1000 correctly:
10
/ \
5 1000
Hence it prints 10 and 1000.
Using a brand new variable solves this problem, because the brand new variable has nothing to do with root.

Deleting Node from BST

I think I got most of the cases to work except for case 2 (deletion node has only one subtree). My test case is the tree below without the 1, 2, 3 and 4 nodes:
This program is telling me that 6 was deleted from the tree but when I try printing the tree, it still shows that 6 is in the tree.
public class RandomNode {
static int size;
public static class Node {
int data;
Node left;
Node right;
public Node(int data) {
this.data = data;
left = null;
right = null;
size++;
}
}
// delete node in right subtree
public Node delete(Node root, int data) {
// base case - if tree is empty
if (root == null)
return root;
// search for deletion node
else if (data < root.data)
root.left = delete(root.left, data);
else if (data > root.data) {
root.right = delete(root.right, data);
} else {
// case 1: deletion node has no subtrees
if (root.left == null && root.right == null) {
root = null;
size--;
System.out.println(data + " successfully deleted from tree (case1)");
// case 2: deletion node has only one subtree
} else if (root.left != null && root.right == null) {
root = root.left;
size--;
System.out.println(data + " successfully deleted from tree (case2a)");
} else if (root.left == null && root.right != null) {
root = root.left;
size--;
System.out.println(data + " successfully deleted from tree (case2b)");
// case 3: deletion node has two subtrees
// *find min value in right subtree
// *replace deletion node with min value
// *remove the min value from right subtree or else there'll be
// a duplicate
} else if (root.left != null && root.right != null) {
Node temp;
if (root.right.right == null && root.right.left == null)
temp = findMinNode(root.left);
else
temp = findMinNode(root.right);
System.out.println(root.data + " replaced with " + temp.data);
root.data = temp.data;
if (root.right.right == null || root.left.left == null)
root.left = delete(root.left, root.data);
else
root.right = delete(root.right, root.data);
size--;
System.out.println(temp.data + " succesfuly deleted from tree (case3)");
}
}
return root;
}
// find min value in tree
public Node findMinNode(Node root) {
while (root.left != null)
root = root.left;
System.out.println("min value: " + root.data);
return root;
}
public void preOrderTraversal(Node root) {
if (root == null)
return;
preOrderTraversal(root.left);
System.out.println(root.data);
preOrderTraversal(root.right);
}
public static void main(String[] args) {
RandomNode r = new RandomNode();
Node root = new Node(6);
//root.left = new Node(2);
root.right = new Node(9);
//root.left.left = new Node(1);
//root.left.right = new Node(5);
//root.left.right.left = new Node(4);
//root.left.right.left.left = new Node(3);
root.right.left = new Node(8);
root.right.right = new Node(13);
root.right.left.left = new Node(7);
root.right.right.left = new Node(11);
root.right.right.right = new Node(18);
r.delete(root, 6);
r.preOrderTraversal(root);
}
}
When you do root = root.left; and size --, you must also make root.left = null.
Here you are simply making root as root.left but are not making root.left as null.
It's rather hard for me to follow since I'd write it functionally.
However,
if (root.right.right == null || root.left.left == null)
root.left = delete(root.left, root.data);
else
root.right = delete(root.right, root.data);
Is probably wrong, since it should mirror your earlier findMinNode() calls, and thus should probably be
if(root.right.right == null && root.right.left == null)
root.left = delete(root.left, root.data);
There is more wrong when debugging it.
First off, java is pass by value, so if you're deleting the top node (root), your pointer should be updated too. Hence, the call should be root = r.delete(root, 6);
Second, there's another bug. Case 2a assigns root to root.left... which is null. It should be root.right.
Having made those changes, the output then becomes:
6 successfully deleted from tree (case2b)
7
8
9
11
13
18

Moving around Java references

So I am creating a Binary Tree through recursion, When I insert a new node I would like to jump back up to the root to start the insert from scratch again. to do that I follow this routine.
BinaryTree node = new BinaryTree();
node = this;
node = root; // this is where I want to get to
So when I coded this out and attempted to set the $this variable to root it did not set as can be seen in this picture.
Why is 'this' not set this to root? how can I jump to the top of a tree?
public void addNode(List teams, BinaryTree tree, BinaryTree root){
while(teams.size() > 1){
print(root);
//Half's the list
halfA = teams.subList(0, teams.size() / 2);
halfB = teams.subList(teams.size() / 2, teams.size());
if(parent == null){
left = new BinaryTree(halfA);
left.parent = this;
right = new BinaryTree(halfB);
right.parent = this;
}
if(countChildren(tree.left) >= countChildren(tree.right)) {
if (right == null) {
setRight(new BinaryTree(halfB));
BinaryTree temp = new BinaryTree();
parent = this;
temp = this;
temp = tree;
} else if (right != null)
right.addNode(halfB, tree, root);
}
if(countChildren(tree.right) >= countChildren(tree.left)) {
if (left == null) {
setLeft(new BinaryTree(halfA));
BinaryTree temp = new BinaryTree();
parent = this;
temp = this;
temp = tree;
} else if (left != null)
left.addNode(halfA, tree, root);
}
}
}

Recursive MergeSort on a Linked List using Java

I searched on the net for a good clean and simple implentation of a merge sort algorithm in Java for a Linked List that uses recursion.
I couldn't find a nice one so Im trying to implement it here. but Im stuck.
Here is what I have so far:
public List mergeSortList(Node head, Node tail) {
if ((head == null) || (head.next == null))
return;
Node middle = this.findMiddle(head);
List left = mergeSortList(this.head, middle);
List right = mergeSortList(middle.next, tail);
return merge(left, right);
}
private List merge(List left, List right) {
List returnedList = new LinkedList();
}
private Node findMiddle(Node n) {
Node slow, fast;
slow = fast = n;
while (fast != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
Can someone help me correct any errors and fill the stubs please.
Thanks
First error is in following :-
while(fast != null && fast.next.next != null)
{
slow = slow.next;
fast = fast.next.next;
}
fast.next can be null when you do fast.next.next , considering the case when no of elements is odd.
Here is a modified code:-
while(fast != null && fast.next.next != null)
{
slow = slow.next;
if(fast.next!=null)
fast = fast.next.next;
else break;
}
Here is another modification:-
public List mergeSortList(Node head)
{
if ( (head == null) || (head.next == null))
return head;
Node middle = this.findMiddle(head);
Node first = head;
Node second = middle.next;
middle.next = null;
Node left = mergeSortList(first);
Node right = mergeSortList(second);
return merge(left, right);
}
Explanation: You donot need to pass tail to the function, You can split the list at middle into two separate list ending with null. And after recursion of two list just reconnect them to prevent loss of original list
Here is clean and simple implementation for Merge Sort on LinkedList
public class MergeSortLinkedList {
static class Node {
Node next;
int value;
Node(int value) {
this.value = value;
}
}
public static void main(String[] args) {
Node head = new Node(10);
head.next = new Node(5);
head.next.next = new Node(2);
head.next.next.next = new Node(1);
head.next.next.next.next = new Node(6);
head.next.next.next.next.next = new Node(8);
head.next.next.next.next.next.next = new Node(3);
head.next.next.next.next.next.next.next = new Node(2);
print(head);
Node sortedHead = mergeSort(head);
print(sortedHead);
}
static void print(Node head) {
Node tmp = head;
while (tmp != null) {
System.out.print(tmp.value + "->");
tmp = tmp.next;
}
System.out.println();
}
static Node getMiddle(Node head) {
if (head == null || head.next == null) {
return head;
}
Node slow = head;
Node fast = head;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
static Node sortedMerge(Node left, Node right) {
if (left == null) {
return right;
}
if (right == null) {
return left;
}
if (left.value < right.value) {
left.next = sortedMerge(left.next, right);
return left;
} else {
right.next = sortedMerge(left, right.next);
return right;
}
}
static Node mergeSort(Node head) {
if (head == null || head.next == null) {
return head;
}
Node middle = getMiddle(head);
Node middleNext = middle.next;
middle.next = null;
Node left = mergeSort(head);
Node right = mergeSort(middleNext);
return sortedMerge(left, right);
}
}
This looks like a good start. Your merge method is going to work just like any other merge sort implementation except you're dealing with lists instead of integers.
What you need to do is:
create a new list to return ('result')
compare the first element in List 'left' to the first in List 'right'
copy the smaller element to the result
advance your pointer into whichever list the smaller element came from
repeat until you hit the end of a list
copy all the remaining elements to the result
Take a stab at that (post your updated code) and we'll be happy to help you out more from there.
Solution divided in two methods,
First method is recursive method what we call from main(), then divide list using fast and slow pointer technique (fast walks 2 step when slow walks one), now call itself recursively with both the lists, and combine returned list using second method mergeSortedList, also we are calling mergeSortedList again and again within the recursion, so at the very end when there is only one element left in each list, we compare them and add together in right order.
ListNode sortList(ListNode head) {
if (head == null || head.next == null) return head;
ListNode fast = head;
ListNode slow = head;
// get in middle of the list :
while (fast.next!= null && fast.next.next !=null){slow = slow.next; fast = fast.next.next;}
fast = slow.next;
slow.next=null;
return mergeSortedList(sortList(head),sortList(fast));
}
ListNode mergeSortedList(ListNode firstList,ListNode secondList){
ListNode returnNode = new ListNode(0);
ListNode trackingPointer = returnNode;
while(firstList!=null && secondList!=null){
if(firstList.val < secondList.val){trackingPointer.next = firstList; firstList=firstList.next;}
else {trackingPointer.next = secondList; secondList=secondList.next;}
trackingPointer = trackingPointer.next;
}
if (firstList!=null) trackingPointer.next = firstList;
else if (secondList!=null) trackingPointer.next = secondList;
return returnNode.next;
}
}
Working solution in java. Go to the link below:
http://ideone.com/4WVYHc
import java.util.*;
import java.lang.*;
import java.io.*;
class Node
{
int data;
Node next;
Node(int data){
this.data = data;
next = null;
}
void append(Node head, int val){
Node temp = new Node(val);
Node cur = head;
if(head == null)
{
return;
}
while(cur.next != null)
{
cur = cur.next;
}
cur.next = temp;
return;
}
void display(){
Node cur = this;
while(cur != null)
{
System.out.print(cur.data + "->");
cur = cur.next;
}
}
}
class Ideone
{
public Node findMiddle(Node head){
if(head == null )
return null;
Node slow, fast;
slow = head;
fast = head;
while(fast != null && fast.next != null && fast.next.next != null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
public Node merge(Node first, Node second){
Node head = null;
while(first != null && second != null){
if(first.data < second.data){
if(head == null){
head = new Node(first.data);
}
else
head.append(head,first.data);
first = first.next;
}
else if(second.data < first.data){
if(head == null){
head = new Node(second.data);
}
else
head.append(head,second.data);
second = second.next;
}
else{
if(head == null){
head = new Node(first.data);
head.append(head,second.data);
}
else{
head.append(head,first.data);
head.append(head,second.data);
}
second = second.next;
first = first.next;
}
}
while(first != null){
if(head == null){
head = new Node(first.data);
}
else
head.append(head,first.data);
first = first.next;
}
while(first != null){
if(head == null){
head = new Node(first.data);
}
else
head.append(head,first.data);
first = first.next;
}
while(second != null){
if(head == null){
head = new Node(second.data);
}
else
head.append(head,second.data);
second = second.next;
}
return head;
}
public Node mergeSort(Node head){
if(head == null)
return null;
if(head.next == null)
return head;
Node first = head;
Node mid = findMiddle(first);
Node second = mid.next;
mid.next = null;
Node left = mergeSort(first);
Node right = mergeSort(second);
Node result = merge(left, right);
return result;
}
public static void main (String[] args) throws java.lang.Exception
{
Node head = new Node(5);
head.append(head,1);
head.append(head,5);
head.append(head,1);
head.append(head,5);
head.append(head,3);
System.out.println("Unsoreted linked list:");
head.display();
Ideone tmp = new Ideone();
Node result = tmp.mergeSort(head);
System.out.println("\nSorted linked list:");
result.display();
}
}
Below is the Java version of the post to sort numbers in linked list using merge sort.
import java.util.ArrayList;
public class SortNumbersInLinkedListUsingMergeSort {
Node head;
public static void main(String[] args) {
SortNumbersInLinkedListUsingMergeSort sll = new SortNumbersInLinkedListUsingMergeSort();
// creating an unsorted linked list
sll.head = new Node(2);
sll.head.next = new Node(5);
sll.head.next.next = new Node(3);
sll.head.next.next.next = new Node(-1);
sll.head.next.next.next.next = new Node(1);
printList(sll.head);
sll.head = Merge(sll.head);
printList(sll.head);
}
//
public static Node Merge(Node head){
// if linked list has no or only one element then return
if (head == null || head.next == null){
return null;
}
// split the linked list into two halves, (front and back as two heads)
ArrayList<Node> list = splitIntoSublists(head);
// Recursively sort the sub linked lists
Merge(list.get(0));
Merge(list.get(1));
// merge two sorted sub lists
head = mergeTwoSortedLists(list.get(0), list.get(1));
return head;
}
// method to merge two sorted linked lists
public static Node mergeTwoSortedLists(Node front, Node back){
Node result;
if (front == null){
return back;
}
if (back == null){
return front;
}
if (front.data >= back.data){
result = back;
result.next = mergeTwoSortedLists(front, back.next);
}
else{
result = front;
result.next = mergeTwoSortedLists(front.next, back);
}
return result;
}
// method to split linked list into two list in middle.
public static ArrayList<Node> splitIntoSublists(Node head){
Node slowPointer;
Node fastPointer ;
Node front = null;
Node back = null;
ArrayList<Node> li = new ArrayList<Node>();
if (head == null || head.next == null){
front = head;
back = null;
}
else{
slowPointer= head;
fastPointer = head.next;
while (fastPointer != null && fastPointer.next != null){
slowPointer = slowPointer.next;
fastPointer = fastPointer.next.next;
}
front = head;
back = slowPointer.next;
slowPointer.next = null;
}
li.add(front);
li.add(back);
return li;
}
// method to print linked list
public static void printList(Node head){
Node pointer = head;
while (pointer != null){
System.out.print(pointer.data + " ");
pointer = pointer.next;
}
System.out.println();
}
}
// class to define linked list
class Node{
int data;
Node next;
public Node (int data){
this.data = data;
}
}
Here is a working example :
public class MergeSort{
public Node head = null;
public class Node {
int val;
Node next;
public Node () {//Constructor
val = 0;
next = null;
}
public Node (int i) { //constructor
val = i;
next = null;
}
}
public void insert ( int i) { //inserts node at the beginning
Node n = new Node(i);
n.next = head;
head = n;
}
public void printList (Node head) {
while (head != null) {
System.out.println (head.val);
head = head.next;
}
}
public Node sort (Node head) {
if ( head == null || head.next ==null ) return head; // no need to sort if there's no node or only one node in the Linked List
Node mid = find_Mid (head); // find middle of the LinkedList
Node sHalf = mid.next ; mid.next = null; //Splitting into two linked lists
Node h = merge ( sort(head), sort(sHalf) ); //Call merge recursively
return h;
}
public Node merge ( Node n1 , Node n2) {
Node curr = null;
if ( n1 == null )
return n2; //n1 empty
if ( n2 == null )
return n1; // n2 empty
if ( n1.val < n2.val ) {
curr=n1;
curr.next = merge (n1.next, n2); //Call merge recursively
}
else {
curr = n2;
curr.next = merge (n1, n2.next); //Call merge recursively
}
return curr;
}
public Node find_Mid (Node head) {
Node slow = head; Node fast = head;
while ( fast.next != null && fast.next.next != null ) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
public static void main(String []args){
System.out.println("Hello World");
MergeSort m = new MergeSort ();
m.insert ( 3 );
m.insert ( 4 );
m.insert ( 16 );
m.insert ( 10 );
m.insert ( 5 );
m.insert ( 1 );
m.insert ( -5 );
m.printList(m.head);
Node n = m.find_Mid (m.head);
System.out.println("Middle is :" + n.val);
m.head = m.sort(m.head);
m.printList(m.head);
}
}

Java Printing a Binary Tree using Level-Order in a Specific Format

Okay, I have read through all the other related questions and cannot find one that helps with java. I get the general idea from deciphering what i can in other languages; but i am yet to figure it out.
Problem: I would like to level sort (which i have working using recursion) and print it out in the general shape of a tree.
So say i have this:
1
/ \
2 3
/ / \
4 5 6
My code prints out the level order like this:
1 2 3 4 5 6
I want to print it out like this:
1
2 3
4 5 6
Now before you give me a moral speech about doing my work... I have already finished my AP Comp Sci project and got curious about this when my teacher mentioned the Breadth First Search thing.
I don't know if it will help, but here is my code so far:
/**
* Calls the levelOrder helper method and prints out in levelOrder.
*/
public void levelOrder()
{
q = new QueueList();
treeHeight = height();
levelOrder(myRoot, q, myLevel);
}
/**
* Helper method that uses recursion to print out the tree in
* levelOrder
*/
private void levelOrder(TreeNode root, QueueList q, int curLev)
{
System.out.print(curLev);
if(root == null)
{
return;
}
if(q.isEmpty())
{
System.out.println(root.getValue());
}
else
{
System.out.print((String)q.dequeue()+", ");
}
if(root.getLeft() != null)
{
q.enqueue(root.getLeft().getValue());
System.out.println();
}
if(root.getRight() != null)
{
q.enqueue(root.getRight().getValue());
System.out.println();
curLev++;
}
levelOrder(root.getLeft(),q, curLev);
levelOrder(root.getRight(),q, curLev);
}
From what i can figure out, i will need to use the total height of the tree, and use a level counter... Only problem is my level counter keeps counting when my levelOrder uses recursion to go back through the tree.
Sorry if this is to much, but some tips would be nice. :)
Here is the code, this question was asked to me in one of the interviews...
public void printTree(TreeNode tmpRoot) {
Queue<TreeNode> currentLevel = new LinkedList<TreeNode>();
Queue<TreeNode> nextLevel = new LinkedList<TreeNode>();
currentLevel.add(tmpRoot);
while (!currentLevel.isEmpty()) {
Iterator<TreeNode> iter = currentLevel.iterator();
while (iter.hasNext()) {
TreeNode currentNode = iter.next();
if (currentNode.left != null) {
nextLevel.add(currentNode.left);
}
if (currentNode.right != null) {
nextLevel.add(currentNode.right);
}
System.out.print(currentNode.value + " ");
}
System.out.println();
currentLevel = nextLevel;
nextLevel = new LinkedList<TreeNode>();
}
}
This is the easiest solution
public void byLevel(Node root){
Queue<Node> level = new LinkedList<>();
level.add(root);
while(!level.isEmpty()){
Node node = level.poll();
System.out.print(node.item + " ");
if(node.leftChild!= null)
level.add(node.leftChild);
if(node.rightChild!= null)
level.add(node.rightChild);
}
}
https://github.com/camluca/Samples/blob/master/Tree.java
in my github you can find other helpful functions in the class Tree like:
Displaying the tree
****......................................................****
42
25 65
12 37 43 87
9 13 30 -- -- -- -- 99
****......................................................****
Inorder traversal
9 12 13 25 30 37 42 43 65 87 99
Preorder traversal
42 25 12 9 13 37 30 65 43 87 99
Postorder traversal
9 13 12 30 37 25 43 99 87 65 42
By Level
42 25 65 12 37 43 87 9 13 30 99
Here is how I would do it:
levelOrder(List<TreeNode> n) {
List<TreeNode> next = new List<TreeNode>();
foreach(TreeNode t : n) {
print(t);
next.Add(t.left);
next.Add(t.right);
}
println();
levelOrder(next);
}
(Was originally going to be real code - got bored partway through, so it's psueodocodey)
Just thought of sharing Anon's suggestion in real java code and fixing a couple of KEY issues (like there is not an end condition for the recursion so it never stops adding to the stack, and not checking for null in the received array gets you a null pointer exception).
Also there is no exception as Eric Hauser suggests, because it is not modifying the collection its looping through, it's modifying a new one.
Here it goes:
public void levelOrder(List<TreeNode> n) {
List<TreeNode> next = new ArrayList<TreeNode>();
for (TreeNode t : n) {
if (t != null) {
System.out.print(t.getValue());
next.add(t.getLeftChild());
next.add(t.getRightChild());
}
}
System.out.println();
if(next.size() > 0)levelOrder(next);
}
Below method returns ArrayList of ArrayList containing all nodes level by level:-
public ArrayList<ArrayList<Integer>> levelOrder(TreeNode root) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
if(root == null) return result;
Queue q1 = new LinkedList();
Queue q2 = new LinkedList();
ArrayList<Integer> list = new ArrayList<Integer>();
q1.add(root);
while(!q1.isEmpty() || !q2.isEmpty()){
while(!q1.isEmpty()){
TreeNode temp = (TreeNode)q1.poll();
list.add(temp.val);
if(temp.left != null) q2.add(temp.left);
if(temp.right != null) q2.add(temp.right);
}
if(list.size() > 0)result.add(new ArrayList<Integer>(list));
list.clear();
while(!q2.isEmpty()){
TreeNode temp = (TreeNode)q2.poll();
list.add(temp.val);
if(temp.left != null) q1.add(temp.left);
if(temp.right != null) q1.add(temp.right);
}
if(list.size() > 0)result.add(new ArrayList<Integer>(list));
list.clear();
}
return result;
}
The answer is close....the only issue I could see with it is that if a tree doesn't have a node in a particular position, you would set that pointer to null. What happens when you try to put a null pointer into the list?
Here is something I did for a recent assignment. It works flawlessly. You can use it starting from any root.
//Prints the tree in level order
public void printTree(){
printTree(root);
}
public void printTree(TreeNode tmpRoot){
//If the first node isn't null....continue on
if(tmpRoot != null){
Queue<TreeNode> currentLevel = new LinkedList<TreeNode>(); //Queue that holds the nodes on the current level
Queue<TreeNode> nextLevel = new LinkedList<TreeNode>(); //Queue the stores the nodes for the next level
int treeHeight = height(tmpRoot); //Stores the height of the current tree
int levelTotal = 0; //keeps track of the total levels printed so we don't pass the height and print a billion "null"s
//put the root on the currnt level's queue
currentLevel.add(tmpRoot);
//while there is still another level to print and we haven't gone past the tree's height
while(!currentLevel.isEmpty()&& (levelTotal< treeHeight)){
//Print the next node on the level, add its childen to the next level's queue, and dequeue the node...do this until the current level has been printed
while(!currentLevel.isEmpty()){
//Print the current value
System.out.print(currentLevel.peek().getValue()+" ");
//If there is a left pointer, put the node on the nextLevel's stack. If there is no ponter, add a node with a null value to the next level's stack
tmpRoot = currentLevel.peek().getLeft();
if(tmpRoot != null)
nextLevel.add(tmpRoot);
else
nextLevel.add(new TreeNode(null));
//If there is a right pointer, put the node on the nextLevel's stack. If there is no ponter, add a node with a null value to the next level's stack
tmpRoot = currentLevel.remove().getRight();
if(tmpRoot != null)
nextLevel.add(tmpRoot);
else
nextLevel.add(new TreeNode(null));
}//end while(!currentLevel.isEmpty())
//populate the currentLevel queue with items from the next level
while(!nextLevel.isEmpty()){
currentLevel.add(nextLevel.remove());
}
//Print a blank line to show height
System.out.println("");
//flag that we are working on the next level
levelTotal++;
}//end while(!currentLevel.isEmpty())
}//end if(tmpRoot != null)
}//end method printTree
public int height(){
return height(getRoot());
}
public int height(TreeNode tmpRoot){
if (tmpRoot == null)
return 0;
int leftHeight = height(tmpRoot.getLeft());
int rightHeight = height(tmpRoot.getRight());
if(leftHeight >= rightHeight)
return leftHeight + 1;
else
return rightHeight + 1;
}
I really like the simplicity of Anon's code; its elegant. But, sometimes elegant code doesn't always translate into code that is intuitively easy to grasp. So, here's my attempt to show a similar approach that requires Log(n) more space, but should read more naturally to those who are most familiar with depth first search (going down the length of a tree)
The following snippet of code sets nodes belonging to a particular level in a list, and arranges that list in a list that holds all the levels of the tree. Hence the List<List<BinaryNode<T>>> that you will see below. The rest should be fairly self explanatory.
public static final <T extends Comparable<T>> void printTreeInLevelOrder(
BinaryTree<T> tree) {
BinaryNode<T> root = tree.getRoot();
List<List<BinaryNode<T>>> levels = new ArrayList<List<BinaryNode<T>>>();
addNodesToLevels(root, levels, 0);
for(List<BinaryNode<T>> level: levels){
for(BinaryNode<T> node: level){
System.out.print(node+ " ");
}
System.out.println();
}
}
private static final <T extends Comparable<T>> void addNodesToLevels(
BinaryNode<T> node, List<List<BinaryNode<T>>> levels, int level) {
if(null == node){
return;
}
List<BinaryNode<T>> levelNodes;
if(levels.size() == level){
levelNodes = new ArrayList<BinaryNode<T>>();
levels.add(level, levelNodes);
}
else{
levelNodes = levels.get(level);
}
levelNodes.add(node);
addNodesToLevels(node.getLeftChild(), levels, level+1);
addNodesToLevels(node.getRightChild(), levels, level+1);
}
Following implementation uses 2 queues. Using ListBlokcingQueue here but any queue would work.
import java.util.concurrent.*;
public class Test5 {
public class Tree {
private String value;
private Tree left;
private Tree right;
public Tree(String value) {
this.value = value;
}
public void setLeft(Tree t) {
this.left = t;
}
public void setRight(Tree t) {
this.right = t;
}
public Tree getLeft() {
return this.left;
}
public Tree getRight() {
return this.right;
}
public String getValue() {
return this.value;
}
}
Tree tree = null;
public void setTree(Tree t) {
this.tree = t;
}
public void printTree() {
LinkedBlockingQueue<Tree> q = new LinkedBlockingQueue<Tree>();
q.add(this.tree);
while (true) {
LinkedBlockingQueue<Tree> subQueue = new LinkedBlockingQueue<Tree>();
while (!q.isEmpty()) {
Tree aTree = q.remove();
System.out.print(aTree.getValue() + ", ");
if (aTree.getLeft() != null) {
subQueue.add(aTree.getLeft());
}
if (aTree.getRight() != null) {
subQueue.add(aTree.getRight());
}
}
System.out.println("");
if (subQueue.isEmpty()) {
return;
} else {
q = subQueue;
}
}
}
public void testPrint() {
Tree a = new Tree("A");
a.setLeft(new Tree("B"));
a.setRight(new Tree("C"));
a.getLeft().setLeft(new Tree("D"));
a.getLeft().setRight(new Tree("E"));
a.getRight().setLeft(new Tree("F"));
a.getRight().setRight(new Tree("G"));
setTree(a);
printTree();
}
public static void main(String args[]) {
Test5 test5 = new Test5();
test5.testPrint();
}
}
public class PrintATreeLevelByLevel {
public static class Node{
int data;
public Node left;
public Node right;
public Node(int data){
this.data = data;
this.left = null;
this.right = null;
}
}
public void printATreeLevelByLevel(Node n){
Queue<Node> queue = new LinkedList<Node>();
queue.add(n);
int node = 1; //because at root
int child = 0; //initialize it with 0
while(queue.size() != 0){
Node n1 = queue.remove();
node--;
System.err.print(n1.data +" ");
if(n1.left !=null){
queue.add(n1.left);
child ++;
}
if(n1.right != null){
queue.add(n1.right);
child ++;
}
if( node == 0){
System.err.println();
node = child ;
child = 0;
}
}
}
public static void main(String[]args){
PrintATreeLevelByLevel obj = new PrintATreeLevelByLevel();
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
Node node6 = new Node(6);
Node node7 = new Node(7);
Node node8 = new Node(8);
node4.left = node2;
node4.right = node6;
node2.left = node1;
// node2.right = node3;
node6.left = node5;
node6.right = node7;
node1.left = node8;
obj.printATreeLevelByLevel(node4);
}
}
Try this, using 2 Queues to keep track of the levels.
public static void printByLevel(Node root){
LinkedList<Node> curLevel = new LinkedList<Node>();
LinkedList<Node> nextLevel = curLevel;
StringBuilder sb = new StringBuilder();
curLevel.add(root);
sb.append(root.data + "\n");
while(nextLevel.size() > 0){
nextLevel = new LinkedList<Node>();
for (int i = 0; i < curLevel.size(); i++){
Node cur = curLevel.get(i);
if (cur.left != null) {
nextLevel.add(cur.left);
sb.append(cur.left.data + " ");
}
if (cur.right != null) {
nextLevel.add(cur.right);
sb.append(cur.right.data + " ");
}
}
if (nextLevel.size() > 0) {
sb.append("\n");
curLevel = nextLevel;
}
}
System.out.println(sb.toString());
}
A - Solution
I've written direct solution here. If you want the detailed answer, demo code and explanation, you can skip and check the rest headings of the answer;
public static <T> void printLevelOrder(TreeNode<T> root) {
System.out.println("Tree;");
System.out.println("*****");
// null check
if(root == null) {
System.out.printf(" Empty\n");
return;
}
MyQueue<TreeNode<T>> queue = new MyQueue<>();
queue.enqueue(root);
while(!queue.isEmpty()) {
handleLevel(queue);
}
}
// process each level
private static <T> void handleLevel(MyQueue<TreeNode<T>> queue) {
int size = queue.size();
for(int i = 0; i < size; i++) {
TreeNode<T> temp = queue.dequeue();
System.out.printf("%s ", temp.data);
queue.enqueue(temp.left);
queue.enqueue(temp.right);
}
System.out.printf("\n");
}
B - Explanation
In order to print a tree in level-order, you should process each level using a simple queue implementation. In my demo, I've written a very minimalist simple queue class called as MyQueue.
Public method printLevelOrder will take the TreeNode<T> object instance root as a parameter which stands for the root of the tree. The private method handleLevel takes the MyQueue instance as a parameter.
On each level, handleLevel method dequeues the queue as much as the size of the queue. The level restriction is controlled as this process is executed only with the size of the queue which exactly equals to the elements of that level then puts a new line character to the output.
C - TreeNode class
public class TreeNode<T> {
T data;
TreeNode<T> left;
TreeNode<T> right;
public TreeNode(T data) {
this.data = data;;
}
}
D - MyQueue class : A simple Queue Implementation
public class MyQueue<T> {
private static class Node<T> {
T data;
Node next;
public Node(T data) {
this(data, null);
}
public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}
}
private Node head;
private Node tail;
private int size;
public MyQueue() {
head = null;
tail = null;
}
public int size() {
return size;
}
public void enqueue(T data) {
if(data == null)
return;
if(head == null)
head = tail = new Node(data);
else {
tail.next = new Node(data);
tail = tail.next;
}
size++;
}
public T dequeue() {
if(tail != null) {
T temp = (T) head.data;
head = head.next;
size--;
return temp;
}
return null;
}
public boolean isEmpty() {
return size == 0;
}
public void printQueue() {
System.out.println("Queue: ");
if(head == null)
return;
else {
Node<T> temp = head;
while(temp != null) {
System.out.printf("%s ", temp.data);
temp = temp.next;
}
}
System.out.printf("%n");
}
}
E - DEMO : Printing Tree in Level-Order
public class LevelOrderPrintDemo {
public static void main(String[] args) {
// root level
TreeNode<Integer> root = new TreeNode<>(1);
// level 1
root.left = new TreeNode<>(2);
root.right = new TreeNode<>(3);
// level 2
root.left.left = new TreeNode<>(4);
root.right.left = new TreeNode<>(5);
root.right.right = new TreeNode<>(6);
/*
* 1 root
* / \
* 2 3 level-1
* / / \
* 4 5 6 level-2
*/
printLevelOrder(root);
}
public static <T> void printLevelOrder(TreeNode<T> root) {
System.out.println("Tree;");
System.out.println("*****");
// null check
if(root == null) {
System.out.printf(" Empty\n");
return;
}
MyQueue<TreeNode<T>> queue = new MyQueue<>();
queue.enqueue(root);
while(!queue.isEmpty()) {
handleLevel(queue);
}
}
// process each level
private static <T> void handleLevel(MyQueue<TreeNode<T>> queue) {
int size = queue.size();
for(int i = 0; i < size; i++) {
TreeNode<T> temp = queue.dequeue();
System.out.printf("%s ", temp.data);
queue.enqueue(temp.left);
queue.enqueue(temp.right);
}
System.out.printf("\n");
}
}
F - Sample Input
1 // root
/ \
2 3 // level-1
/ / \
4 5 6 // level-2
G - Sample Output
Tree;
*****
1
2 3
4 5 6
public void printAllLevels(BNode node, int h){
int i;
for(i=1;i<=h;i++){
printLevel(node,i);
System.out.println();
}
}
public void printLevel(BNode node, int level){
if (node==null)
return;
if (level==1)
System.out.print(node.value + " ");
else if (level>1){
printLevel(node.left, level-1);
printLevel(node.right, level-1);
}
}
public int height(BNode node) {
if (node == null) {
return 0;
} else {
return 1 + Math.max(height(node.left),
height(node.right));
}
}
First of all, I do not like to take credit for this solution. It's a modification of somebody's function and I tailored it to provide the solution.
I am using 3 functions here.
First I calculate the height of the tree.
I then have a function to print a particular level of the tree.
Using the height of the tree and the function to print the level of a tree, I traverse the tree and iterate and print all levels of the tree using my third function.
I hope this helps.
EDIT: The time complexity on this solution for printing all node in level order traversal will not be O(n). The reason being, each time you go down a level, you will visit the same nodes again and again.
If you are looking for a O(n) solution, i think using Queues would be a better option.
I think we can achieve this by using one queue itself. This is a java implementation using one queue only. Based on BFS...
public void BFSPrint()
{
Queue<Node> q = new LinkedList<Node>();
q.offer(root);
BFSPrint(q);
}
private void BFSPrint(Queue<Node> q)
{
if(q.isEmpty())
return;
int qLen = q.size(),i=0;
/*limiting it to q size when it is passed,
this will make it print in next lines. if we use iterator instead,
we will again have same output as question, because iterator
will end only q empties*/
while(i<qLen)
{
Node current = q.remove();
System.out.print(current.data+" ");
if(current.left!=null)
q.offer(current.left);
if(current.right!=null)
q.offer(current.right);
i++;
}
System.out.println();
BFSPrint(q);
}
the top solutions only print the children of each node together. This is wrong according to the description.
What we need is all the nodes of the same level together in the same line.
1) Apply BFS
2) Store heights of nodes to a map that will hold level - list of nodes.
3) Iterate over the map and print out the results.
See Java code below:
public void printByLevel(Node root){
Queue<Node> q = new LinkedBlockingQueue<Node>();
root.visited = true;
root.height=1;
q.add(root);
//Node height - list of nodes with same level
Map<Integer, List<Node>> buckets = new HashMap<Integer, List<Node>>();
addToBuckets(buckets, root);
while (!q.isEmpty()){
Node r = q.poll();
if (r.adjacent!=null)
for (Node n : r.adjacent){
if (!n.visited){
n.height = r.height+1; //adjust new height
addToBuckets(buckets, n);
n.visited = true;
q.add(n);
}
}
}
//iterate over buckets and print each list
printMap(buckets);
}
//helper method that adds to Buckets list
private void addToBuckets(Map<Integer, List<Node>> buckets, Node n){
List<Node> currlist = buckets.get(n.height);
if (currlist==null)
{
List<Node> list = new ArrayList<Node>();
list.add(n);
buckets.put(n.height, list);
}
else{
currlist.add(n);
}
}
//prints the Map
private void printMap(Map<Integer, List<Node>> buckets){
for (Entry<Integer, List<Node>> e : buckets.entrySet()){
for (Node n : e.getValue()){
System.out.print(n.value + " ");
}
System.out.println();
}
Simplest way to do this without using any level information implicitly assumed to be in each Node. Just append a 'null' node after each level. check for this null node to know when to print a new line:
public class BST{
private Node<T> head;
BST(){}
public void setHead(Node<T> val){head = val;}
public static void printBinaryTreebyLevels(Node<T> head){
if(head == null) return;
Queue<Node<T>> q = new LinkedList<>();//assuming you have type inference (JDK 7)
q.add(head);
q.add(null);
while(q.size() > 0){
Node n = q.poll();
if(n == null){
System.out.println();
q.add(null);
n = q.poll();
}
System.out.print(n.value+" ");
if(n.left != null) q.add(n.left);
if(n.right != null) q.add(n.right);
}
}
public static void main(String[] args){
BST b = new BST();
c = buildListedList().getHead();//assume we have access to this for the sake of the example
b.setHead(c);
printBinaryTreeByLevels();
return;
}
}
class Node<T extends Number>{
public Node left, right;
public T value;
Node(T val){value = val;}
}
This works for me. Pass an array list with rootnode when calling printLevel.
void printLevel(ArrayList<Node> n){
ArrayList<Node> next = new ArrayList<Node>();
for (Node t: n) {
System.out.print(t.value+" ");
if (t.left!= null)
next.add(t.left);
if (t.right!=null)
next.add(t.right);
}
System.out.println();
if (next.size()!=0)
printLevel(next);
}
Print Binary Tree in level order with a single Queue:
public void printBFSWithQueue() {
java.util.LinkedList<Node> ll = new LinkedList<>();
ll.addLast(root);
ll.addLast(null);
Node in = null;
StringBuilder sb = new StringBuilder();
while(!ll.isEmpty()) {
if(ll.peekFirst() == null) {
if(ll.size() == 1) {
break;
}
ll.removeFirst();
System.out.println(sb);
sb = new StringBuilder();
ll.addLast(null);
continue;
}
in = ll.pollFirst();
sb.append(in.v).append(" ");
if(in.left != null) {
ll.addLast(in.left);
}
if(in.right != null) {
ll.addLast(in.right);
}
}
}
void printTreePerLevel(Node root)
{
Queue<Node> q= new LinkedList<Node>();
q.add(root);
int currentlevel=1;
int nextlevel=0;
List<Integer> values= new ArrayList<Integer>();
while(!q.isEmpty())
{
Node node = q.remove();
currentlevel--;
values.add(node.value);
if(node.left != null)
{
q.add(node.left);
nextlevel++;
}
if(node.right != null)
{
q.add(node.right);
nextlevel++;
}
if(currentlevel==0)
{
for(Integer i:values)
{
System.out.print(i + ",");
}
System.out.println();
values.clear();
currentlevel=nextlevel;
nextlevel=0;
}
}
}
Python implementation
# Function to print level order traversal of tree
def printLevelOrder(root):
h = height(root)
for i in range(1, h+1):
printGivenLevel(root, i)
# Print nodes at a given level
def printGivenLevel(root , level):
if root is None:
return
if level == 1:
print "%d" %(root.data),
elif level > 1 :
printGivenLevel(root.left , level-1)
printGivenLevel(root.right , level-1)
""" Compute the height of a tree--the number of nodes
along the longest path from the root node down to
the farthest leaf node
"""
def height(node):
if node is None:
return 0
else :
# Compute the height of each subtree
lheight = height(node.left)
rheight = height(node.right)
#Use the larger one
if lheight > rheight :
return lheight+1
else:
return rheight+1
Queue<Node> queue = new LinkedList<>();
queue.add(root);
Node leftMost = null;
while (!queue.isEmpty()) {
Node node = queue.poll();
if (leftMost == node) {
System.out.println();
leftMost = null;
}
System.out.print(node.getData() + " ");
Node left = node.getLeft();
if (left != null) {
queue.add(left);
if (leftMost == null) {
leftMost = left;
}
}
Node right = node.getRight();
if (right != null) {
queue.add(right);
if (leftMost == null) {
leftMost = right;
}
}
}
To solve this type of question which require in-level or same-level traversal approach, one immediately can use Breath First Search or in short BFS. To implement the BFS one can use Queue. In Queue each item comes in order of insertion, so for example if a node has two children, we can insert its children into queue one after another, thus make them in order inserted. When in return polling from queue, we traverse over children as it like we go in same-level of tree. Hense I am going to use a simple implementation of an in-order traversal approach.
I build up my Tree and pass the root which points to the root.
inorderTraversal takes root and do a while-loop that peeks one node first, and fetches children and insert them back into queue. Note that nodes one by one get inserted into queue, as you see, once you fetch the children nodes, you append it to the StringBuilder to construct the final output.
In levelOrderTraversal method though, I want to print the tree in level order. So I need to do the above approach, but instead I don't poll from queue and insert its children back to queue. Because I intent to insert "next-line-character" in a loop, and if I insert the children to queue, this loop would continue inserting a new line for each node, instead I need to check do it only for a level. That's why I used a for-loop to check how many items I have in my queue.
I simply don't poll anything from queue, because I only want to know if there are any level exists.
This separation of method helps me to still keep using BFS data and when required I can print them in-order or level-order , based-on requirements of the application.
public class LevelOrderTraversal {
public static void main(String[] args) throws InterruptedException {
BinaryTreeNode node1 = new BinaryTreeNode(100);
BinaryTreeNode node2 = new BinaryTreeNode(50);
BinaryTreeNode node3 = new BinaryTreeNode(200);
node1.left = node2;
node1.right = node3;
BinaryTreeNode node4 = new BinaryTreeNode(25);
BinaryTreeNode node5 = new BinaryTreeNode(75);
node2.left = node4;
node2.right = node5;
BinaryTreeNode node6 = new BinaryTreeNode(350);
node3.right = node6;
String levelOrderTraversal = levelOrderTraversal(node1);
System.out.println(levelOrderTraversal);
String inorderTraversal = inorderTraversal(node1);
System.out.println(inorderTraversal);
}
private static String inorderTraversal(BinaryTreeNode root) {
Queue<BinaryTreeNode> queue = new LinkedList<>();
StringBuilder sb = new StringBuilder();
queue.offer(root);
BinaryTreeNode node;
while ((node = queue.poll()) != null) {
sb.append(node.data).append(",");
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
return sb.toString();
}
public static String levelOrderTraversal(BinaryTreeNode root) {
Queue<BinaryTreeNode> queue = new LinkedList<>();
queue.offer(root);
StringBuilder stringBuilder = new StringBuilder();
while (!queue.isEmpty()) {
handleLevelPrinting(stringBuilder, queue);
}
return stringBuilder.toString();
}
private static void handleLevelPrinting(StringBuilder sb, Queue<BinaryTreeNode> queue) {
for (int i = 0; i < queue.size(); i++) {
BinaryTreeNode node = queue.poll();
if (node != null) {
sb.append(node.data).append("\t");
queue.offer(node.left);
queue.offer(node.right);
}
}
sb.append("\n");
}
private static class BinaryTreeNode {
int data;
BinaryTreeNode right;
BinaryTreeNode left;
public BinaryTreeNode(int data) {
this.data = data;
}
}
}
Wow. So many answers. For what it is worth, my solution goes like this:
We know the normal way to level order traversal: for each node, first the node is visited and then it’s child nodes are put in a FIFO queue. What we need to do is keep track of each level, so that all the nodes at that level are printed in one line, without a new line.
So I naturally thought of it as miaintaining a queue of queues. The main queue contains internal queues for each level. Each internal queue contains all the nodes in one level in FIFO order. When we dequeue an internal queue, we iterate through it, adding all its children to a new queue, and adding this queue to the main queue.
public static void printByLevel(Node root) {
Queue<Node> firstQ = new LinkedList<>();
firstQ.add(root);
Queue<Queue<Node>> mainQ = new LinkedList<>();
mainQ.add(firstQ);
while (!mainQ.isEmpty()) {
Queue<Node> levelQ = mainQ.remove();
Queue<Node> nextLevelQ = new LinkedList<>();
for (Node x : levelQ) {
System.out.print(x.key + " ");
if (x.left != null) nextLevelQ.add(x.left);
if (x.right != null) nextLevelQ.add(x.right);
}
if (!nextLevelQ.isEmpty()) mainQ.add(nextLevelQ);
System.out.println();
}
}
public void printAtLevel(int i){
printAtLevel(root,i);
}
private void printAtLevel(BTNode<T> n,int i){
if(n != null){
sop(n.data);
} else {
printAtLevel(n.left,i-1);
printAtLevel(n.right,i-1);
}
}
private void printAtLevel(BTNode<T> n,int i){
if(n != null){
sop(n.data);
printAtLevel(n.left,i-1);
printAtLevel(n.right,i-1);
}
}

Categories

Resources