Tree traversing doesn't print desired solution - java

(java)
I have class called Node, which has following fields:
value (integer)
connectedNodes (array of Node objects, always has same size = 2)
combination (object of Combination class)
Combination class has one field called messageContext, let's just say that it's a message which needs to be shown on the screen when something happens (described later).
Also, we have one Tree object, which has only one field: root (Node object)
Now, let's say that we have one String called combinationStr = "1121". Now, we use Tree's method called addCombination:
public void addCombination(Combination finalCombination, Node current, String combination, int counter) {
if(counter==combination.length()) {
return;
}
int value = combination.charAt(counter)-48;
if(current.connectedNodes[value-1]==null) {
current.connectedNodes[value-1] = new Node(value);
}
if(counter==combination.length()-1) {
current.combination = finalCombination;
return;
}
addCombination(finalCombination,current.connectedNodes[value-1],combination,counter+1);
}
finalCombination object is an object that is going to be assigned to the last Node's combination field, added to the Tree for one combinationStr. So, we use this function to create the Tree-like structure that has path: -1 (root) -> 1 -> 1 -> 2 -> 1
When we come to the last one, traversing the Tree, we should see message appear. This is the messageContext of finalCombination.
Okay so, now let's use while(true) loop that will let us input a number, which will be like a path-chooser. If we input 1, we will go to node 1 and have other options to choose.
While loop looks like this:
Scanner scanner = new Scanner(System.in);
Node currentNode = tree.root;
while(true) {
for(Node node: currentNode.connectedNodes) {
if(node!=null) {
System.out.print(node.value + " ");
continue;
}
System.out.print("nullnode ");
}
System.out.println("");
if(currentNode.combination!=null) {
System.out.println(currentNode.combination.messageContext);
}
if(currentNode.connectedNodes[0]==null && currentNode.connectedNodes[1]==null) {
currentNode = tree.root;
System.out.println("root");
}
int x = scanner.nextInt();
currentNode = tree.takeStep(currentNode,x);
}
So, what are we doing here is actually printing the value of current Node, then printing values of Node's we can go to. If Node doesn't exist, we print nullnode.
The takeStep() method looks like this:
public Node takeStep(Node current, int value) {
if(current.connectedNodes[value-1]!=null) {
return current.connectedNodes[value-1];
}
return this.root;
}
It just checks if there is a node we want to go to and returns that node, if it does. If it doesn't exist, it will return us to root.
But, what's the problem with this code ?
Well, look at the whole main class:
Tree tree = new Tree(new Node(-1));
String[] combination = {"1121","11","2212"};
for(String s: combination) {
Combination tempCombination = new Combination();
tempCombination.messageContext = s + " ova poruka";
tree.addCombination(tempCombination,tree.root,s,0);
tree.traverse(tree.root);
System.out.println("END");
}
Scanner scanner = new Scanner(System.in);
Node currentNode = tree.root;
while(true) {
System.out.println(currentNode.value);
for(Node node: currentNode.connectedNodes) {
if(node!=null) {
System.out.print(node.value + " ");
}
else {
System.out.print("nullnode ");
}
}
int x = scanner.nextInt();
if(currentNode.combination!=null) {
System.out.println(currentNode.combination.messageContext);
if(currentNode.connectedNodes[0]==null && currentNode.connectedNodes[1]==null) {
currentNode = tree.root;
break;
}
}
currentNode = tree.takeStep(currentNode,x);
}
When we enter number x, we will call takeStep and check if that node exists connected to current one. But the problem is: When we input 1, it prints everything normally, when we input 1 again, it prints everything normally, when we input 2, it prints everything normally... but when we input 1 again, it says there are 2 nullnodes, and for some reason it doesn't change to root. Can anyone help me please? Here are the full classes:
NODE:
public class Node {
int value;
Node[] connectedNodes = {null,null};
Combination combination;
public Node(int value) {
this.value = value;
this.combination = null;
}
}
TREE:
public class Tree {
Node root;
public Tree(Node root) {
this.root = root;
}
public void addCombination(Combination finalCombination, Node current, String combination, int counter) {
if(counter==combination.length()) {
return;
}
int value = combination.charAt(counter)-48;
if(current.connectedNodes[value-1]==null) {
current.connectedNodes[value-1] = new Node(value);
}
if(counter==combination.length()-1) {
current.combination = finalCombination;
return;
}
addCombination(finalCombination,current.connectedNodes[value-1],combination,counter+1);
}
public void traverse(Node current) {
System.out.print(current.value+ " ");
for(Node node: current.connectedNodes) {
if(node!=null) {
traverse(node);
}
}
}
public Node takeStep(Node current, int value) {
if(current.connectedNodes[value-1]!=null) {
return current.connectedNodes[value-1];
}
return this.root;
}}
COMBINATION:
public class Combination {
String messageContext;
}
Can you please help me ? I just want to reset to root when it hasn't anywhere to go else ? Thank you in advance!

I ran your code and found out that you are storing the message context in the parent node instead of the actual node which marks the end of the combination. So I changed this piece of code in addCombination.
public void addCombination(Combination finalCombination, Node current, String combination, int counter) {
if (counter == combination.length()) {
//Storing at the original node.
current.combination = finalCombination;
return;
}
int value = combination.charAt(counter) - 48;
if (current.connectedNodes[value - 1] == null) {
current.connectedNodes[value - 1] = new Node(value);
}
addCombination(finalCombination, current.connectedNodes[value - 1], combination, counter + 1);
}
And changed following in the main code.
while (true) {
System.out.println(currentNode.value);
//Moved it up now as the node it self has the message context.
if (currentNode.combination != null) {
System.out.println(currentNode.combination.messageContext);
if (currentNode.connectedNodes[0] == null && currentNode.connectedNodes[1] == null) {
currentNode = tree.root;
continue;
}
}
for (Node node : currentNode.connectedNodes) {
if (node != null) {
System.out.print(node.value + " ");
} else {
System.out.print("nullnode ");
}
}
int x = scanner.nextInt();
currentNode = tree.takeStep(currentNode, x);
}
Now try the code it is resetting to root as expected.

Related

Getting all possible paths in a tree structure

I need to loop in a tree to get all possible paths, the problem in my code that i get just the first path!
example:
In the figure, there are 2 paths t handle: 1-2-3-4-5-6 and 1-2-3-7-8 , but i couldn't get both, i have just retrieved 1-2-3-4-5-6 !
my code:
In main:
for (String key : synset.keySet()) { // looping in a hash of Concept and it's ID
System.out.println("\nConcept: " + key + " " + synset.get(key));
List<Concept> ancts = myOntology.getConceptAncestors(myOntology.getConceptFromConceptID(synset.get(key))); // this function retreives the root of any node.
for (int i = 0; i < ancts.size(); i++) {
System.out.print(ancts.get(i).getConceptId() + " # ");
System.out.print(getChilds(ancts.get(i).getConceptId()) + " -> "); // here, the recursive function is needed to navigate into childs..
}
System.out.println("");
}
Rec. function:
public static String getChilds(String conId)
{
List<Concept> childs = myOntology.getDirectChildren(myOntology.getConceptFromConceptID(conId)); // get all childs of a node
if(childs.size() > 0)
{
for (int i = 0; i < childs.size(); i++) {
System.out.print( childs.size() + " ~ " + childs.get(i).getConceptId() + " -> ");
return getChilds(childs.get(i).getConceptId());
}
}
else
return "NULL";
return "final";
}
I didn't really see enough of your code to use the classes that you have defined. So I went for writing my own working solution.
In the following code, the problem is solved using recursion:
public class TreeNode {
private String id;
private TreeNode parent;
private List<TreeNode> children;
public TreeNode(String id) {
this.id = id;
this.children = new LinkedList<>();
}
public void addChild(TreeNode child) {
this.children.add(child);
child.setParent(this);
}
public List<TreeNode> getChildren() {
return Collections.unmodifiableList(this.children);
}
private void setParent(TreeNode parent) {
this.parent = parent;
}
public TreeNode getParent() {
return this.parent;
}
public String getId() {
return this.id;
}
}
public class TreePaths {
private static List<List<TreeNode>> getPaths0(TreeNode pos) {
List<List<TreeNode>> retLists = new ArrayList<>();
if(pos.getChildren().size() == 0) {
List<TreeNode> leafList = new LinkedList<>();
leafList.add(pos);
retLists.add(leafList);
} else {
for (TreeNode node : pos.getChildren()) {
List<List<TreeNode>> nodeLists = getPaths0(node);
for (List<TreeNode> nodeList : nodeLists) {
nodeList.add(0, pos);
retLists.add(nodeList);
}
}
}
return retLists;
}
public static List<List<TreeNode>> getPaths(TreeNode head) {
if(head == null) {
return new ArrayList<>();
} else {
return getPaths0(head);
}
}
}
To use the above code, a tree must be constructed using the TreeNode class. Start off by creating a head TreeNode, then add child nodes to it as required. The head is then submitted to the TreePaths getPaths static function.
After getPaths checks for null, the internal getPaths0 function will be called. Here we follow a depth first approach by trying to get to all leaf nodes as soon as possible. Once a leaf node is found, a List only containing this leaf node will be created and returned inside the list collection. The parent of this leaf node will then be added to the beginning of the list, which will again be put into a list collection. This will happen for all children of the parent.
In the end, all possible paths will end up in a single structure. This function can be tested as follows:
public class TreePathsTest {
TreeNode[] nodes = new TreeNode[10];
#Before
public void init() {
int count = 0;
for(TreeNode child : nodes) {
nodes[count] = new TreeNode(String.valueOf(count));
count++;
}
}
/*
* 0 - 1 - 3
* - 4
* - 2 - 5
* - 6
* - 7 - 8
* - 9
*/
private void constructBasicTree() {
nodes[0].addChild(nodes[1]);
nodes[0].addChild(nodes[2]);
nodes[1].addChild(nodes[3]);
nodes[1].addChild(nodes[4]);
nodes[2].addChild(nodes[5]);
nodes[2].addChild(nodes[6]);
nodes[2].addChild(nodes[7]);
nodes[7].addChild(nodes[8]);
nodes[7].addChild(nodes[9]);
}
#Test
public void testPaths() {
constructBasicTree();
List<List<TreeNode>> lists = TreePaths.getPaths(nodes[0]);
for(List<TreeNode> list : lists) {
for(int count = 0; count < list.size(); count++) {
System.out.print(list.get(count).getId());
if(count != list.size() - 1) {
System.out.print("-");
}
}
System.out.println();
}
}
}
This will print out:
0-1-3
0-1-4
0-2-5
0-2-6
0-2-7-8
0-2-7-9
Note: The above is enough for manual testing, but the test function should be modified to do proper assertions for proper automated unit testing.
maybe this code segment in getChilds() exist problem:
for (int i = 0; i < childs.size(); i++) {
System.out.print( childs.size() + " ~ " + childs.get(i).getConceptId() + " -> ");
return getChilds(childs.get(i).getConceptId());
}
the for loop cant play a role, it always return getChilds(childs.get(0).getConceptId());
maybe this is not what you want.
One simple way.
All you need is a tree traversal and little bit of custom code.
Have a list called tempPath. you can take it as an argument or a global variable.
Do a tree traversal(eg. inorder). Whenever you are at a node add this to tempPath list at the end and when you are done with this node remove the node from the end of tempPath.
whenever you encounter a leaf, you have one full path from root to leaf which is contained in tempPath. you can either print or copy this list value into another data structure.

How to get the level of a node in a generic tree?

Given a generic tree implemented as a root node with a list of sons, which sons are nodes and again each node has a list of its sons.
__A__
/ | \
B C D
| / \
E F G
The node A has a list of its sons: B, C, D
B, C, D also have a list of their sons: B --> E ; C --> F, G ; D --> null ;
I will explain my idea of the algorithm, you can fix it or give me another completely new idea.
public Integer level(T dato) {...}
Traverse the tree adding to the queue each node of the tree or adding a "null" if the last node added is the last node of the level. Null is an identifier in the queue to know where the level has ended.
My problem is that I don't know exactly where to put the identifier after the first time.
Here is some of the code:
public Integer level(T data){
int inclu= this.include(data);
if (inclu==-1) { // if the tree doesn't include the data
return -1;
} else {
return inclu; // returns the level
}
}
public Integer include( T data ) { // returns the level where the data is
Integer inclu = -1; // -1 if the data is not included
if (this.getDataRoot()==data){
return 0; // The root of the tree has the data
}
else {
LinkedList<GenericNode<T>> queue = new LinkedList<GenericNode<T>>();
GenericNode<T> tree = new GenericNode<T>();
int level=1;
queue.addAtBeginning(this.getRoot());
queue.addAtBeginning(null);
while (queue.size()>0 && inclu==-1) {
if(queue.element(queue.size())!=null) { // if it is not the end of the level then dequeue
tree.setData(queue.element(queue.size()).getData()); //queue.element(position) returns the element in that position
tree.setListOfSons(queue.element(queue.size()).getSons());
if (tree.getSons()!=null) { // if the tree has sons
int i=1;
while(i<=tree.getSons().size() && inclu==-1) {
queue.addAtBeginning(tree.getSons().element(i));
if (tree.getSons().element(i).getData()==data) // if I found the data I'm looking for
inclu=level;
i++; // counter
}
}
} else { // if it is the end of the level (means the queue gave me a null)
level++;
}
queue.delete(queue.size()); //ending the dequeue process
} //end while
} // end main else
return inclu; //returns the summation of the levels or 0 if it was found at the root of the tree or -1 if the data was not found
}
I wrote a class that returns the level of target node in specific tree.
import java.util.LinkedList;
import java.util.List;
public class TreeLevel {
public static class Node {
public Node(String data) { this.data = data ; };
public String data;
public List<Node> childs = new LinkedList<Node>();
}
public static Integer level(Node tree, Node target){
return level(tree, target, 0);
}
private static Integer level(Node tree, Node target, int currentLevel) {
Integer returnLevel = -1;
if(tree.data.equals(target.data)) {
returnLevel = currentLevel;
} else {
for(Node child : tree.childs) {
if((returnLevel = level(child, target, currentLevel + 1)) != -1){
break;
}
}
}
return returnLevel;
}
public static void main(String[] args) {
Node a = new Node("A");
Node b = new Node("B");
Node c = new Node("C");
Node d = new Node("D");
Node e = new Node("E");
Node f = new Node("F");
Node g = new Node("G");
// childs of a:
a.childs.add(b);
a.childs.add(c);
a.childs.add(d);
// childs of b:
b.childs.add(e);
// childs of c:
c.childs.add(f);
c.childs.add(g);
// childs of d:
// d.childs = null or simply d.childs.length() is 0
Node target = new Node("G");
Integer level = level(a, target);
System.out.println("level [" + level + "]");
}
}
I think I can give you a simple code for this question. You can change the it according to your code.
public Integer include( T data ) { // returns the level where the data is
Integer inclu = -1; // -1 if the data is not included
if (this.getDataRoot() == data){
return 0; // The root of the tree has the data
}
return level(this.getRoot(), data, 1);
}
//Find data in a tree whose root is Node
//If not found, return -1
public int level(T node, T data, int level) {
if (!node.hasChildren()) {
return -1;
}
for (T child : node.getChildren()) {
if (child.getData == data) {
return level; //Aha!!! found it
} else {
int l = level(child, data, level + 1); /// find in this sub-tree
if (l != -1) {
return l;
}
}
}
return -1; /// Not found in this sub-tree.
}
P.S : == is used to compare, which is not good. .equals() should be used.

BinaryTree implementation in java

I have this code for BinaryTree creation and traversal
class Node
{
Integer data;
Node left;
Node right;
Node()
{
data = null;
left = null;
right = null;
}
}
class BinaryTree
{
Node head;
Scanner input = new Scanner(System.in);
BinaryTree()
{
head = null;
}
public void createNode(Node temp, Integer value)
{
Node newnode= new Node();
value = getData();
newnode.data = value;
temp = newnode;
if(head==null)
{
head = temp;
}
System.out.println("If left child exits for ("+value+") enter y else n");
if(input.next().charAt(0)=='y')
{
createNode(temp.left, value);
}
System.out.println("If right child exits for ("+value+") enter y else n");
if(input.next().charAt(0)=='y')
{
createNode(temp.right, value);
}
}
public Integer getData()
{
out.println("Enter the value to insert:");
return (Integer)input.nextInt();
}
public void print()
{
inorder(head);
}
public void inorder(Node node)
{
if(node!=null)
{
inorder(node.left);
System.out.println(node.data);
inorder(node.right);
}
else
return;
}
}
class BinaryTreeWorker
{
static BinaryTree treeObj = null;
static Scanner input = new Scanner(System.in);
public static void displaymenu()
{
int choice;
do{
out.print("\n Basic operations on a tree:");
out.print("\n 1. Create tree \n 2. Insert \n 3. Search value \n 4. print list\n Else. Exit \n Choice:");
choice = input.nextInt();
switch(choice)
{
case 1:
treeObj = createBTree();
break;
case 2:
treeObj.createNode(null, null);
break;
case 3:
//searchnode();
break;
case 4:
treeObj.print();
break;
default:
return;
}
}while(true);
}
public static BinaryTree createBTree()
{
return new BinaryTree();
}
public static void main(String[] args)
{
displaymenu();
}
}
It compiles and runs. But I think there is something wrong with the inorder traversal.
I created the below tree,
2
1 3
But it prints only 2.
I have tried solving the problem your way and I have pasted the solution below.. Though I haven't tested it thoroughly so it might fail in some edge condition.. But I have tested it for one case. Kindly let me know if it fails in some scenario. I would appreciate others help in making this answer better. I agree that this solution is not the most ideal way to code a Binary Tree but it wont hurt this way if some one is just practicing..
import java.util.Scanner;
class Node
{
Integer data;
Node left;
Node right;
Node()
{
data = null;
left = null;
right = null;
}
}
class BinaryTree
{
Node head;
Scanner input = new Scanner(System.in);
BinaryTree()
{
head = null;
}
public void createNode(Node temp,Node newnode)
{
if(head==null)
{
System.out.println("No value exist in tree, the value just entered is set to Root");
head = newnode;
return;
}
if(temp==null)
temp = head;
System.out.println("where you want to insert this value, l for left of ("+temp.data+") ,r for right of ("+temp.data+")");
char inputValue=input.next().charAt(0);
if(inputValue=='l'){
if(temp.left==null)
{
temp.left=newnode;
System.out.println("value got successfully added to left of ("+temp.data+")");
return;
}else {
System.out.println("value left to ("+temp.data+") is occupied 1by ("+temp.left.data+")");
createNode(temp.left,newnode);
}
}
else if(inputValue=='r')
{
if(temp.right==null)
{
temp.right=newnode;
System.out.println("value got successfully added to right of ("+temp.data+")");
return;
}else {
System.out.println("value right to ("+temp.data+") is occupied by ("+temp.right.data+")");
createNode(temp.right,newnode);
}
}else{
System.out.println("incorrect input plz try again , correctly");
return;
}
}
public Node generateTree(){
int [] a = new int[10];
int index = 0;
while(index<a.length){
a[index]=getData();
index++;
}
if(a.length==0 ){
return null;
}
Node newnode= new Node();
/*newnode.left=null;
newnode.right=null;*/
return generateTreeWithArray(newnode,a,0);
}
public Node generateTreeWithArray(Node head,int [] a,int index){
if(index >= a.length)
return null;
System.out.println("at index "+index+" value is "+a[index]);
if(head==null)
head= new Node();
head.data = a[index];
head.left=generateTreeWithArray(head.left,a,index*2+1);
head.right=generateTreeWithArray(head.right,a,index*2+2);
return head;
}
public Integer getData()
{
System.out.println("Enter the value to insert:");
return (Integer)input.nextInt();
}
public void print()
{
inorder(head);
}
public void inorder(Node node)
{
if(node!=null)
{
inorder(node.left);
System.out.println(node.data);
inorder(node.right);
}
else
return;
}
}
public class BinaryTreeWorker
{
static BinaryTree treeObj = null;
static Scanner input = new Scanner(System.in);
public static void displaymenu()
{
int choice;
do{
System.out.print("\n Basic operations on a tree:");
System.out.print("\n 1. Create tree \n 2. Insert \n 3. Search value \n 4. print list\n 5. generate a tree \n Else. Exit \n Choice:");
choice = input.nextInt();
switch(choice)
{
case 1:
treeObj = createBTree();
break;
case 2:
Node newnode= new Node();
newnode.data = getData();
newnode.left=null;
newnode.right=null;
treeObj.createNode(treeObj.head,newnode);
break;
case 3:
//searchnode();
break;
case 4:
System.out.println("inorder traversal of list gives follows");
treeObj.print();
break;
case 5:
Node tempHead = treeObj.generateTree();
System.out.println("inorder traversal of list with head = ("+tempHead.data+")gives follows");
treeObj.inorder(tempHead);
break;
default:
return;
}
}while(true);
}
public static Integer getData()
{
System.out.println("Enter the value to insert:");
return (Integer)input.nextInt();
}
public static BinaryTree createBTree()
{
return new BinaryTree();
}
public static void main(String[] args)
{
displaymenu();
}
}
[Update] : Updated the code to generate a binary tree using an array. This will involve less user interaction.
Best way to implement Binary Tree in Java with all the traverse types and test cases as below
package com.nitin.tree;
public class Tree
{
private Node parent;
private int data;
private int size = 0;
public Tree() {
parent = new Node(data);
}
public void add(int data) {
if (size == 0) {
parent.data = data;
size++;
} else {
add(parent, new Node(data));
}
}
private void add(Node root, Node newNode) {
if (root == null) {
return;
}
if (newNode.data < root.data) {
if (root.left == null) {
root.left = newNode;
size++;
} else {
add(root.left, newNode);
}
} else {
if (root.right == null) {
root.right = newNode;
size++;
} else {
add(root.right, newNode);
}
}
}
public int getLow() {
Node current = parent;
while (current.left != null) {
current = current.left;
}
return current.data;
}
public int getHigh() {
Node current = parent;
while (current.right != null) {
current = current.right;
}
return current.data;
}
private void in(Node node) {
if (node != null) {
in(node.left);
System.out.print(node.data + " ");
in(node.right);
}
}
private void pre(Node node) {
if (node != null) {
System.out.print(node.data + " ");
pre(node.left);
pre(node.right);
}
}
private void post(Node node) {
if (node != null) {
post(node.left);
post(node.right);
System.out.print(node.data + " ");
}
}
public void preorder() {
System.out.print("Preorder Traversal->");
pre(parent);
System.out.println();
}
public void postorder() {
System.out.print("Postorder Traversal->");
post(parent);
System.out.println();
}
public void inorder() {
System.out.print("Inorder Traversal->");
in(parent);
System.out.println();
}
private class Node {
Node left;
Node right;
int data;
public Node(int data) {
this.data = data;
}
}
public String toString() {
Node current = parent;
System.out.print("Traverse From Left ");
while (current.left != null && current.right != null) {
System.out.print(current.data + "->[" + current.left.data + " " + current.right.data + "] ");
current = current.left;
}
System.out.println();
System.out.print("Traverse From Right ");
current = parent;
while (current.left != null && current.right != null) {
System.out.print(current.data + "->[" + current.left.data + " " + current.right.data + "] ");
current = current.right;
}
return "";
}
public static void main(String af[]) {
Tree t = new Tree();
t.add(40);
t.add(25);
t.add(78);
t.add(10);
t.add(32);
t.add(50);
t.add(93);
t.add(3);
t.add(17);
t.add(30);
t.add(38);
System.out.println(t.getLow());
System.out.println(t.getHigh());
System.out.println("Size-" + t.size);
System.out.println(t);
t.inorder();
t.preorder();
t.postorder();
}
}
Your problem is in public void createNodes(Node temp, T data) function. You pass in a parameter the same name as the class variable temp. First of all I don't think you need the class variable by itself. Second of all assigning to temp in this method has only local effect - you loose the information in the temp parameter, but setting temp, will not infuence its value in the called method. I suggest you rewrite the method so that it returns the pointer to the newly created node and assign this pointer to the left and right of the local temp. That way the changes will propagate out.
another type of outputting the tree:
public void inorder()
{
inorder(root);
}
protected void visit(BSTNode<T> p)
{
System.out.println("Node: " + p.el + "Left Side:" + (p.left!=null?p.left.el:"null") +
"Right Side:" + (p.right!=null?p.right.el:"null"));
}
I've changed the BinaryTree Class as below. See the change on the the createNode method in particular.
The problem, as mentioned in the post before this, is that your reference doesn't persist when it is passed as an argument to the createNode method. That change is only local. You need to return an explicit Node reference in the method itself as you're creating the node.
public Node createNode()
{
Integer value = getData();
Node temp = new Node(value);
if(head==null)
{
head = temp;
}
System.out.println("Do you want to add left branch on node("+value+")? Enter y/n");
if(input.next().charAt(0)=='y')
{
temp.left=createNode();
}
System.out.println("Do you want to add right branch on node("+value+")? Enter y/n");
if(input.next().charAt(0)=='y')
{
temp.right=createNode();
}
return temp;
}
Here is the resulting output:
Basic operations on a tree:
1. Create tree
2. Insert
3. Search value
4. print list
Else. Exit
Choice:1
Basic operations on a tree:
1. Create tree
2. Insert
3. Search value
4. print list
Else. Exit
Choice:2
Enter the value to insert:
10
Do you want to add left branch on node(10)? Enter y/n
y
Enter the value to insert:
20
Do you want to add left branch on node(20)? Enter y/n
n
Do you want to add right branch on node(20)? Enter y/n
n
Do you want to add right branch on node(10)? Enter y/n
y
Enter the value to insert:
30
Do you want to add left branch on node(30)? Enter y/n
n
Do you want to add right branch on node(30)? Enter y/n
n
Basic operations on a tree:
1. Create tree
2. Insert
3. Search value
4. print list
Else. Exit
Choice:4
20
10
30
I hope this will be of some help to someone later (even if this is 3 years late..). I just started learning about Binary Trees today myself. I'm actually planning on using this as a base to doing more involved tasks!
I changed the createNode method so that it works:
public Node createNode(Node temp, Integer value)
{
Node newnode = new Node();
value = getData();
newnode.data = value;
temp = newnode;
if(head == null)
{
head = temp;
}
System.out.println("If left child exits for ("+value+") enter y else n");
if(input.next().charAt(0) == 'y')
{
newnode.left = createNode(newnode.left, value);
}
System.out.println("If right child exits for ("+value+") enter y else n");
if(input.next().charAt(0) == 'y')
{
newnode.right = createNode(newnode.right, value);
}
return newnode;
}

AVL Tree Traversal, Search problems

I am having a few problems in my AVL tree implementation.. The code for all the rotations and the adding all seem to be correct and I dry-run the program to thoroughly check that it is running logically correct. I seem to be having a problem in my tree traversal (in-order) because it only outputs a few integers from the supposed 100. Also the search is always failing, regardless of what I enter. I cannot seem to grasp what is going on but I suspect that it has something to do with a few null pointers. Below is the code for the AVL tree, I am wondering if there's any incorrect code in the AddNode method or the rotation methods but they seem to be fine.. The classes are Node class, AVL class and AVL tree class which is the main class.
Node class
private int data;
private Node left;
private Node right;
private int height;
public Node(int m) {
data = m;
left = null;
right = null;
height = 0;
}
public void setToleft(Node newleft) {
left = newleft;
}
public Node getleftNode() {
return left;
}
public void setToright(Node newright) {
right = newright;
}
public Node getrightNode() {
return right;
}
public int getData() {
return data;
}
public int getHeight(){
return height;
}
public void setHeight(int height){
this.height = height;
}
AVL class
public Node root;
public AVL(int root) {
this.root = new Node(root); // since root presently has no left or right children, height is currently 0
}
public int Height(Node n) {
if (n == null) { //basis step
return -1;
} else { //add one for every path
if (n.getleftNode() == null && n.getrightNode() == null) {
return 0;
}
return 1 + Math.max(Height(n.getleftNode()), Height(n.getrightNode()));
}
}
public void add(int data) {
addNode(data, root);
root.setHeight(Math.max(Height(root.getleftNode()), Height(root.getrightNode())) + 1);
}
public void addNode(int data, Node n) {
if (data < n.getData()) {
if (n.getleftNode() == null) {
n.setToleft(new Node(data));
} else {
addNode(data, n.getleftNode());
}
n.setHeight(Math.max(Height(n.getleftNode()), Height(n.getrightNode())) + 1);
if ((Height(n.getleftNode()) + 1) - (Height(n.getrightNode()) + 1) == Math.abs(2)) {
if (data < n.getleftNode().getData()) {
n = LLRotation(n);
} else {
n = LRRotation(n);
}
}
} else if (data >= n.getData()) { //>= also caters for duplicates and inserts them infront of same value
if (n.getrightNode() == null) {
n.setToright(new Node(data));
} else {
addNode(data, n.getrightNode());
}
n.setHeight(Math.max(Height(n.getleftNode()), Height(n.getrightNode())) + 1);
if ((Height(n.getrightNode()) + 1) - (Height(n.getleftNode()) + 1) == Math.abs(2)) {
if (data >= n.getrightNode().getData()) {
n = RRRotation(n);
} else {
n = RLRotation(n);
}
}
}
}
public Node LLRotation(Node n) { //single
Node n1 = n.getleftNode();
n.setToleft(n1.getrightNode());
n1.setToright(n);
n.setHeight(Math.max(Height(n.getleftNode()), Height(n.getrightNode())) + 1);
n1.setHeight(Math.max(Height(n1.getleftNode()), Height(n)) + 1);
//compares heights of left and right subtrees and gets max
//the above source code is of course vital since the node height must be resetted after rotations
//adding 1 at the end of the last two code lines is important since
//initially the height is only calculated from subtrees onwards
//same for single right rotation below
return n1;
}
public Node RRRotation(Node n) { //single
Node n1 = n.getrightNode();
n.setToright(n1.getleftNode());
n1.setToleft(n);
n.setHeight(Math.max(Height(n.getleftNode()), Height(n.getrightNode())) + 1);
n1.setHeight(Math.max(Height(n1.getrightNode()), Height(n)) + 1);
return n1;
}
public Node LRRotation(Node n) { //double
n.setToleft(RRRotation(n.getleftNode()));
return LLRotation(n);
}
public Node RLRotation(Node n) { //double
n.setToright(LLRotation(n.getrightNode()));
return RRRotation(n);
}
public void inOrderTraversal(Node n) {
if (n != null) {
inOrderTraversal(n.getleftNode()); //recursive call to the left subtree
System.out.println(n.getData()); //line which makes the actual node to display its data
inOrderTraversal(n.getrightNode()); //recursive call to the right subtree
}
}
public void traverse() {
inOrderTraversal(root); // can be called in main class to automatically traverse tree from its root
}
public int search(int x) {
try {
if (x == root.getData()) { //basis step
System.out.println("Item found!");
return x;
}
if (x < root.getData()) {
root = root.getleftNode();
return search(x);//recursive call
} else {
root = root.getrightNode();
return search(x);//recursive call
}
} catch (NullPointerException e) {
System.out.println ("Search failed!");
return 0;
}
}
Main Class
public static void main(String[] args) throws IOException {
Scanner s = new Scanner(System.in);
AVL tree = null;
int choice = 0;
System.out.println("AVL TREE");
System.out.println("\n Choose an option from the menu: ");
System.out.println("\n\t 1.) Create file of 100 integers");
System.out.println("\n\t 2.) Create the tree");
System.out.println("\n\t 3.) In-Order traverse and show tree");
System.out.println("\n\t 4.) Search for integer");
System.out.println("\n\t 5.) Quit");
while (choice != 5) {
System.out.print("\nChoice: ");
choice = s.nextInt();
switch (choice) {
case 1:
createFile();
break;
case 2:
try {
FileReader readto = new FileReader("Integers.txt");
BufferedReader br = new BufferedReader(readto);
String line = br.readLine(); //reads text at start of file
line = br.readLine(); // skipping empty lines
line = br.readLine();
line = br.readLine();
int root = Integer.parseInt(line); //extracts first integer from the line
System.out.println("Root: " + root);
tree = new AVL(root);
int x = 0;
while (x != 99) {
try {
line = br.readLine();
int next = Integer.parseInt(line);
tree.add(next);
System.out.println(next);
x++;
} catch (NumberFormatException e) {
};
}
System.out.println("Tree successfully populated!");
} catch (FileNotFoundException e) {
System.out.println("ERROR: File not found!");
}
break;
case 3:
System.out.println("In-Order traversel executed. The now balanced tree shall now be printed in");
System.out.println("ascending order and also the left and right children of each node shall be printed.\n");
System.out.println("Traversal: ");
tree.traverse();
break;
case 4:
System.out.print("Please enter the integer to be searched: ");
int x = s.nextInt();
System.out.println(tree.search(x));
break;
case 5:
System.exit(0);
break;
default:
System.out.println("ERROR: Choice out of bounds!");
}
}
}
static void createFile() throws IOException {
Random r = new Random();
File intfile = new File("Integers.txt");
FileWriter writeto = new FileWriter("Integers.txt");
BufferedWriter bw = new BufferedWriter(writeto);
if (!(intfile.exists())) {
System.out.println("ERROR: File not found!");
} else {
bw.write("The following integers are randomly generated");
bw.newLine();
bw.write("and will be used to construct the AVL tree:");
bw.newLine();
bw.newLine();
int x;
System.out.println("The following random numbers shall be used to build the AVL tree: \n");
for (int i = 0; i < 100; i++) {
x = r.nextInt(100) + 1;
bw.write(String.valueOf(x));
bw.newLine();
System.out.println(x);
}
bw.close();
}
}
The output for the traversal is just the following:
Traversal:
44
53
54
54
77
Suppose that there were 100 integers entered and among them were these. But the output for the traversal was only this.
Output for the search is like this:
Choice: 4
Please enter the integer to be searched: 44
Item found!
44
Choice: 4
Please enter the integer to be searched: 100
Search failed!
0
100 and 44 were both integers added to the tree, but 44 was found and 100 wasn't.. I don;t understand..
Anyone can guide me to a solution..?
Thanks in advance :)
Well, first the obvious thing... In your search method, you are abusing the root variable, which holds the root of your tree, setting it to new values as your search proceeds. So, after the first search, root points to the last node traversed in the search and no longer to the root node of the tree. All following searches are unlikely to find anything at all from that point on.
As your search is recursive, try passing on the node-to-be-searched-in as parameter:
int search(Node node, int key) {
if (node == null) {
return 0; // missing from tree
} else if (key < node.getData()) {
return search(node.getLeft(), key);
} else if (key > node.getData()) {
return search(node.getRight(), key);
} else {
return node.getData(); // found it
}
}
(Edited to address the comments) You might have to expose this method like you do with your add/addNode method pair using a publicly available wrapper, and an internal implementation:
public int search(int key) {
return searchNode(root, key);
}
private int searchNode(Node node, int key) {
// Perform the recursive search, as above
}
There are other problems related to your add/addNode methods. Maybe I just overlooked it, but nowhere do you adjust the root node of your tree, if rotation would make it necessary. This, in effect, causes your tree to get out of balance, losing the AVL property over time.

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