I am trying to perform an iterative breadth first traversal, iterative depth first traversal, and recursive depth first traversal of a given graph (using an adjacency matrix).
In its current state, my program outputs various wrong answers.
Here's some examples.
I am expecting
From Node A
DFS (iterative): A B H C D E I F G
DFS (recursive): A B H C D E I F G
BFS (iterative): A B D I H C E F G
but am instead getting
From Node A
DFS (iterative): A I D B H C F G E
DFS (recursive): A B H C F D E I G
BFS (iterative): A B D I H C E F G
I'm unsure if the problem with my program lies within the implementation of the traversals, or my implementation of some other part of the program. To be more specific, I'm not sure if my implementation connectNode or getNeighbors method is what is causing the incorrect output, or if it is my implementation of the traversals.
EDIT: Neighbors are supposed to be chosen in ascending order, if that's important. Perhaps this is part of the problem?
EDIT2: I added the new line of code, thanks to #HylianPikachu's suggestion. I now get full answers, but they are still not in the correct order.
EDIT3: I added the code to make it so the root node is checked as visited for bfs and recursive dfs. I think. I should also note that I was given parts of this code and told to fill in the rest. The use of the stack and queue are what I was told to use, even though there might be better options.
EDIT4: Added what was suggested, and now, the Iterative BFS works and gets the correct result. However, both DSF searches still do not work. I modified the results of the program above, to show this.
import java.util.*;
public class GraphM {
public Node rootNode;
public List<Node> nodes = new ArrayList<Node>(); // nodes in graph
public int[][] adjMatrix; // adjacency Matrix
public void setRootNode(Node n) {
rootNode = n;
}
public Node getRootNode() {
return rootNode;
}
public void addNode(Node n) {
nodes.add(n);
}
// This method connects two nodes
public void connectNode(Node src, Node dst) {
if(adjMatrix == null) {
adjMatrix = new int[nodes.size()][nodes.size()];
}
adjMatrix[nodes.indexOf(src)][nodes.indexOf(dst)] = 1;
adjMatrix[nodes.indexOf(dst)][nodes.indexOf(src)] = 1;
}
// Helper method to get one unvisited node from a given node n.
private Node getUnvisitedChildNode(Node n) {
int index = nodes.indexOf(n);
int size = adjMatrix.length;
for (int j = 0; j < size; j++)
if (adjMatrix[index][j] == 1 && ((Node) nodes.get(j)).visited == false)
return nodes.get(j);
return null;
}
// get all neighboring nodes of node n.
public List<Node> getNeighbors(Node n) {
List<Node> neighbors = new ArrayList<Node>();
for(int i = 0; i < nodes.size(); i ++) {
if (adjMatrix[nodes.indexOf(n)][i] == 1) {
neighbors.add(nodes.get(i));
}
Collections.sort(neighbors);
}
return neighbors;
}
// Helper methods for clearing visited property of node
private void reset() {
for (Node n : nodes)
n.visited = false;
}
// Helper methods for printing the node label
private void printNode(Node n) {
System.out.print(n.label + " ");
}
// BFS traversal (iterative version)
public void bfs() {
Queue<Node> queue = new LinkedList<Node>();
queue.add(rootNode);
while(!queue.isEmpty()) {
Node node = queue.poll();
printNode(node);
node.visited = true;
List<Node> neighbors = getNeighbors(node);
for ( int i = 0; i < neighbors.size(); i ++) {
Node n = neighbors.get(i);
if (n != null && n.visited != true) {
queue.add(n);
n.visited = true;
}
}
}
}
// DFS traversal (iterative version)
public void dfs() {
Stack<Node> stack = new Stack<Node>();
stack.add(rootNode);
while(!stack.isEmpty()){
Node node = stack.pop();
if(node.visited != true) {
printNode(node);
node.visited = true;
}
List<Node> neighbors = getNeighbors(node);
for (int i = 0; i < neighbors.size(); i++) {
Node n = neighbors.get(i);
if(n != null && n.visited != true) {
stack.add(n);
}
}
}
}
// DFS traversal (recursive version)
public void dfs(Node n) {
printNode(n);
n.visited = true;
List<Node> neighbors = getNeighbors(n);
for (int i = 0; i < neighbors.size(); i ++) {
Node node = neighbors.get(i);
if(node != null && node.visited != true) {
dfs(node);
}
}
}
// A simple Node class
static class Node implements Comparable<Node> {
public char label;
public boolean visited = false;
public Node(char label) {
this.label = label;
}
public int compareTo(Node node) {
return Character.compare(this.label, node.label);
}
}
// Test everything
public static void main(String[] args) {
Node n0 = new Node('A');
Node n1 = new Node('B');
Node n2 = new Node('C');
Node n3 = new Node('D');
Node n4 = new Node('E');
Node n5 = new Node('F');
Node n6 = new Node('G');
Node n7 = new Node('H');
Node n8 = new Node('I');
// Create the graph (by adding nodes and edges between nodes)
GraphM g = new GraphM();
g.addNode(n0);
g.addNode(n1);
g.addNode(n2);
g.addNode(n3);
g.addNode(n4);
g.addNode(n5);
g.addNode(n6);
g.addNode(n7);
g.addNode(n8);
g.connectNode(n0, n1);
g.connectNode(n0, n3);
g.connectNode(n0, n8);
g.connectNode(n1, n7);
g.connectNode(n2, n7);
g.connectNode(n2, n3);
g.connectNode(n3, n4);
g.connectNode(n4, n8);
g.connectNode(n5, n6);
g.connectNode(n5, n2);
// Perform the DFS and BFS traversal of the graph
for (Node n : g.nodes) {
g.setRootNode(n);
System.out.print("From node ");
g.printNode(n);
System.out.print("\nDFS (iterative): ");
g.dfs();
g.reset();
System.out.print("\nDFS (recursive): ");
g.dfs(g.getRootNode());
g.reset();
System.out.print("\nBFS (iterative): ");
g.bfs();
g.reset();
System.out.println("\n");
}
}
}
So, we already covered the first part of your question, but I'll restate it here for those who follow. Whenever working with graphs and an adjacency matrix, probably the best way to initialize elements in the array is "both ways."
Instead of just using the following, which would require a specific vertex be listed first in order to find the neighbors:
adjMatrix[nodes.indexOf(src)][nodes.indexOf(dst)] = 1;
Use this, which leads to searches that are agnostic of the vertex order:
adjMatrix[nodes.indexOf(src)][nodes.indexOf(dst)] = 1;
adjMatrix[nodes.indexOf(dst)][nodes.indexOf(src)] = 1;
Now, for ordering. You want the vertices to be outputted in order from "least" letter to "greatest" letter. We'll address each one of your data structures individually.
In BFS (iterative), you use a Queue. Queues are "first in, first out." In other words, the element that was least recently added to the Queue will be outputted first whenever you call queue.poll(). Thus, you need to add your nodes from least to greatest.
In DFS (iterative), you use a Stack. Stacks are "last in, first out." In other words, the element that was most recently added to the Stack will be outputted first whenever you call stack.pop(). Thus, you need to add your nodes from greatest to least.
In DFS (recursive), you use a List. Lists have no "in-out" ordering per se, as we can poll them in whatever order we want, but the easiest thing to do would just be to sort the List from least to greatest and output them in order.
With this in mind, we need to introduce protocol for sorting the graph. All three protocols use getNeighbors(), so we'll sort the outputted List immediately after we call that function. Lists can be ordered with the function Collections.sort(List l) from java.utils.Collections, but we first need to modify your nodes class so Java knows how to sort the Nodes. For further reading about the details of what I'm doing, you can look here, but this post is getting way longer than I intended already, so I'm going to just show the code here and let the interested explore the link themselves.
You would first tweak your Node class by implementing Comparable<Node> and adding the compareTo() function.
static class Node implements Comparable<Node>{
public char label;
public boolean visited = false;
public Node(char label) {
this.label = label;
}
#Override
public int compareTo(Node that) {
return Character.compare(this.label, that.label);
}
}
Then, in the cases in which we want to order the List from least to greatest, we can use Collections.sort(neighbors). When we want it from greatest to least, we can use Collections.sort(neighbors, Collections.reverseOrder()). Our final code will look like this:
// BFS traversal (iterative version)
public void bfs() {
Queue<Node> queue = new LinkedList<Node>();
queue.add(rootNode);
while(!queue.isEmpty()) {
Node node = queue.poll();
printNode(node);
node.visited = true;
List<Node> neighbors = getNeighbors(node);
//NEW CODE: Sort our neighbors List!
Collections.sort(neighbors);
for ( int i = 0; i < neighbors.size(); i ++) {
Node n = neighbors.get(i);
if (n != null && n.visited != true) {
queue.add(n);
n.visited = true;
}
}
}
}
// DFS traversal (iterative version)
public void dfs() {
Stack<Node> stack = new Stack<Node>();
stack.add(rootNode);
while(!stack.isEmpty()){
Node node = stack.pop();
if(node.visited != true) {
printNode(node);
node.visited = true;
}
List<Node> neighbors = getNeighbors(node);
//NEW CODE: Sort our neighbors List in reverse order!
Collections.sort(neighbors, Collections.reverseOrder());
for (int i = 0; i < neighbors.size(); i++) {
Node n = neighbors.get(i);
if(n != null && n.visited != true) {
stack.add(n);
}
}
}
}
// DFS traversal (recursive version)
public void dfs(Node n) {
printNode(n);
n.visited = true;
List<Node> neighbors = getNeighbors(n);
//NEW CODE: Sort our neighbors List!
Collections.sort(neighbors);
for (int i = 0; i < neighbors.size(); i ++) {
Node node = neighbors.get(i);
if(node != null && node.visited != true) {
dfs(node);
}
}
}
I would suggest splitting up your problem into smaller parts.
If you want to write a class for an undirected graph, first do that and test it a bit.
If you want to look if you can implement traversal, make sure your graph works first. You can also use guava, which lets you use MutableGraph (and lots more). Here is how to install it in case you're using IntelliJ and here is how to use graphs from guava.
Also remember to use a debugger to find out were your code goes wrong.
Two weeks ago I've finished an implementation of a splay tree that allows basic functions, like insert, delete, find key and and obtain the sum of a range of elements of the three. You can find this implementation here as reference for this question or out of curiosity.
As an extra task (its optional and its past due, I'm solving this not for a grade but because I believe its a useful data structure not easy to "Google about it"), I was asked to implement a Rope data structure to manipulate strings so if the string is "warlock" and the keys given are 0 2 2, then the string would be "lowarck" (0 2 is substring "war", "lock" is whats left after removing "war" and you insert it after 2nd char so turns into "lo"+"war"+"ck").
This is just one query but it can be up to 100k queries for a 300k character long string, so a naive solution wouldnt work.
My first doubt is about initializing the tree( For the ones who have read the gist,I'll use Node instead of Vertex in order to be easy to understand for most).
This is the Node class and the NodePair class:
class Node {
char key;
int size;
Node left;
Node right;
Node parent;
Node(char key, int size, Node left, Node right, Node parent) {
this.key = key;
this.size = size;
this.left = left;
this.right = right;
this.parent = parent;
}
}
class NodePair {
Node left;
Node right;
NodePair() {
}
NodePair(Node left, Node right) {
this.left = left;
this.right = right;
}
}
After that, I create the tree this way:
StringBuffer sb = new StringBuffer(br.readLine());
Node left=null;
for (int i=0;i<sb.length();i++){
root=new Vertex(sb.charAt(i), i+1, left, null, null);
if (i!=sb.length()-1){
left=root;
}
}
This creates a very unbalanced tree where the first char of the string (as node.key) has node.size 1 and is the leftmost child; and the last char of the string is the root with size=sb.length().
I am not completely sure if this is correctly initialized. I did an inorder traversal print with key and size and I got the whole string in size order, which is what I expected.
After that I have modified the Update method from this:
void update(Node v) {
if (v == null) return;
v.sum = v.key + (v.left != null ? v.left.sum : 0) + (v.right != null ? v.right.sum : 0);
if (v.left != null) {
v.left.parent = v;
}
if (v.right != null) {
v.right.parent = v;
}
}
To this: (based on CLRS chapter 14.1)
void update(Node v) {
if (v == null) return;
v.size = 1 + (v.left != null ? v.left.size : 0) + (v.right != null ? v.right.size : 0);
if (v.left != null) {
v.left.parent = v;
}
if (v.right != null) {
v.right.parent = v;
}
}
Then the find method, from the original:
NodePair find(Node root, int key) {
Node v = root;
Node last = root;
Node next = null;
while (v != null) {
if (v.key >= key && (next == null || v.key < next.key)) {
next = v;
}
last = v;
if (v.key == key) {
break;
}
if (v.key < key) {
v = v.right;
} else {
v = v.left;
}
}
root = splay(last);
return new NodePair(next, root);
}
to this:(Based in the Order Statistics-SELECT of CLRS Chapter 14.1)
Node find(Node r, int k){
int s = r.left.size + 1;
if (k==s) return r;
else if (k < s) {
return find(r.left,k);
}
return find(r.right,k-s);
}
However I already have a problem at this point since, as you can see, the original find returns a NodePair while this method returns a Node.
The explanation of the NodePair according to instructors is:
Returns pair of the result and the new root.If found, result is a
pointer to the node with the given key.Otherwise, result is a pointer
to the node with the smallest bigger key (next value in the order). If
the key is bigger than all keys in the tree, then result is null.
This complicates my split method since it uses Find method to look for the node to split.
Besides this, I'm obtaining NullPointerException at this find method and from other students I understand that to avoid other error we should use a non-recursive version, so basically I need to implement a non-recursive version of OS-Select that returns a NodePair as the previous find method or modify my split method which is:
NodePair split(Node root, int key) {
NodePair result = new NodePair();
NodePair findAndRoot = find(root, key);
root = findAndRoot.right;
result.right = findAndRoot.left;
if (result.right == null) {
result.left = root;
return result;
}
result.right = splay(result.right);
result.left = result.right.left;
result.right.left = null;
if (result.left != null) {
result.left.parent = null;
}
update(result.left);
update(result.right);
return result;
}
As you can see, the find method is assigned to the NodePair findAndRoot.
I believe that besides the OS-Select conversion to non-recursive my main problem is to understand the way NodePair is used by the previous find method and split method.
Finally, this is my implementation of the method to receive the tree and keys and manipulate them:
Node stringManip(Node v, int i, int j, int k){
Node left;
Node right;
NodePair middleRight =split(v,j+1);
left=middleRight.left;
right=middleRight.right;
NodePair leftMiddle = split(left,i);
Node start = leftMiddle.left;
Node substr = leftMiddle.right;
Node tmp = merge(start, right);
NodePair pairString = split(tmp,k+1);
Vertex fLeft =pairString.left;
Vertex fRight = pairString.right;
root = merge(merge(fLeft,substr),fRight);
root = splay(root);
update(root);
return root;
}
As you must realize from my code, I'm a beginner with only have 5 months that started learning to program and I picked Java, so from the info I've gathered I get that this type of data structure is more in the intermediate-expert level (I'm already surprise I was capable of implementing the previous splay tree.
So please, consider my beginner level in your answer.
PD: Here's a pseudocode version of the nonrecursive OS-Select, still having NullPointerException..
OS-SELECT(x, i)
while x != null
r <- size[left[x]]+1
if i = r
then return x
elseif i < r
x = left[x]
else
x = right[x]
i = i - r
I know how to find the depth of a binary tree. But I cannot generalize it to work for any tree.
Can someone please outline a pseudo code for finding the depth of a tree (not necessarily a binary tree).
int findDepthOfTree(tree):
int deepest = 0;
for (child of root node)
deepest = max(deepest, findDepthOfTree(child))
return deepest + 1
Java implementation to find depth of a k-ary tree:
static int findDepth(Node root) {
int deepest = 0;
if (root.children != null) {
for (Node child : root.children) {
deepest = Math.max(deepest, findDepth(child));
}
}
return deepest+1;
}
This assumes the following Node class is implemented to hava a data element as well as a reference to the list of nodes representing its children. Would be something like this:
class Node {
int data;
List<Node> children;
public Node (int data, List<Node> children) {
this.data = data;
this.children = children;
}
public Node (int data) {
this.data = data;
this.children = null;
}
}
public static int GetMaxDepth(MyTree node)
{
List<int> result = new List<int>();
foreach (var childNode in node.Items)
{
result.Add(GetMaxDepth(childNode));
}
return (result.Any() ? result.Max(n => n) : 0) + 1;
}
Recursive StreamAPI solution: O(n)
int calculateMaxDepth(Node node) {
if (node == null)
return 0;
var localDepth = node.children
.stream()
.map(NodeService::calculateMaxDepth)
.max(Comparator.naturalOrder())
.orElse(0); // if root has no children -> return 0
return ++localDepth;
}
Iterative Queue solution: O(n)
int calculateMaxDepth(Node rootNode) {
if (rootNode == null) return 0;
int height = 0;
// level representing queue
Queue<Node> nodesQueue = new LinkedList<>();
nodesQueue.add(rootNode);
while (true) {
// amount of nodes on level
int nodesCount = nodesQueue.size();
if (nodesCount == 0) return height;
++height;
// deque all nodes of current level and
// enqueue all nodes of next level
while (nodesCount > 0) {
var currentLevelNode = nodesQueue.remove();
var validChildrenNodes = currentLevelNode.children
.parallelStream()
.filter(Objects::nonNull)
.collect(Collectors.toList());
nodesQueue.addAll(validChildrenNodes);
--nodesCount;
}
}
}
For additional info you can visit:
https://www.geeksforgeeks.org/write-a-c-program-to-find-the-maximum-depth-or-height-of-a-tree/
https://www.geeksforgeeks.org/iterative-method-to-find-height-of-binary-tree/
Following is my implementation of lowest common ancestor for a Binary Search tree. I have two question:
1) The time complexity is O(n) and space complexity is O(n) worse case but O(logn) average case for both time and space if BST is balanced. is that correct?
2) How can i extend my solution to binary trees and not just binary search trees.
Hope to hear from you soon.
//The function findOrQueue is to enqueue all elements upto target node to a queue
public void findOrQueue(Node target, Node top, LLQueue q) {
int cmp = target.getData().compareTo(top.getData());
if(cmp == 0) {
q.enqueue(top);
return ;
}
else if (cmp < 0) {
q.enqueue(top);
findOrQueue(target, top.getLeftChild(),q);
}
else {
q.enqueue(top);
findOrQueue(target, top.getRightChild(),q);
}
}
public Node LCA(Node n1, Node n2) throws QueueEmptyException {
LLQueue q1 = new LLQueue();
LLQueue q2 = new LLQueue();
findOrQueue(n1,getRoot(),q1);
findOrQueue(n2,getRoot(),q2);
Node t = null;
while (!q1.isEmpty() && !q2.isEmpty()) {
Node t1 = (Node)q1.dequeue();
Node t2 = (Node)q2.dequeue();
if(t1.getData() != t2.getData()) {
return t;
}
else t = t1;
}
if(q1.isEmpty() && q2.isEmpty())
return null;
else
return t;
}
The key to extending your solution to a general binary tree seems to lie in finding the path connecting the root and a target node. Once obtaining this path, you could easily modify your LCA function to find the lowest common ancestor.
The following crude implementation makes use of LinkedBlockingQueue in package java.util.concurrent.* and Stack in java.util.* - however, any other ordinary queue and stack would also do the trick. The code assumes that the target nodes exists in the tree.
public static void findPath2(Node target,Node top, Stack<Node> path){
LinkedBlockingQueue<Node> q1 = new LinkedBlockingQueue<Node>(), q2 = new LinkedBlockingQueue<Node>(),
q3 = new LinkedBlockingQueue<Node>();
Node n = top;
Node parrent = null;
while(n.getData().compareTo(target.getData())!= 0){
parrent = n;
if(n.right != null){
q2.add(n.right);
q3.add(parrent);
}
if(n.left != null){
q2.add(n.left);
q3.add(parrent);
}
n = q2.remove();
q1.add(n);
}
Stack<Node> s3 = new Stack<Node>(), s2 = new Stack<Node>();
while(!q3.isEmpty()){
s3.push(q3.remove());
}
for(int i = 1; i <= q2.size(); i++)
s3.pop();
while(!s3.isEmpty())
s2.push(s3.pop());
while(!q1.isEmpty())
s3.push(q1.remove());
LinkedBlockingQueue<Node> temp = new LinkedBlockingQueue<Node>();
while(!s2.isEmpty())
temp.add(s2.pop());
while(!temp.isEmpty())
s2.push(temp.remove());
path.push(s3.pop());
path.push(s2.pop());
while(!s3.isEmpty()){
n = s3.peek();
while(n.getData().compareTo(path.peek().getData()) != 0 && !s3.isEmpty()){
s3.pop();
s2.pop();
if(!s3.isEmpty())
n = s3.peek();
}
if(!s3.isEmpty()){
s3.pop();
path.push(s2.pop());
}
}
}
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);
}
}