Reputation: 7183
How to keep track of the level while traversing a binary tree in level order or breadth-first order?
The nodes in the binary tree have left and right references only.
I want to be able to distinguish between each row of nodes.
Here is my method for level-order traversal:
private static Queue<Node> traverseLevelOrder(final Node node)
{
final Queue<Node> temporaryQueue = new LinkedList<Node>(); // Temporary queue is used for traversal.
final Queue<Node> permanentQueue = new LinkedList<Node>(); // Permanent queue is used for node storage.
// Add the root node, as current, to the queue.
Node current = node;
temporaryQueue.add(current);
permanentQueue.add(current);
while (!temporaryQueue.isEmpty())
{
current = temporaryQueue.remove();
System.out.println(String.valueOf(current));
// Check current's children.
if (current != null)
{
final Node left = current.getLeft();
final Node right = current.getRight();
current = left;
if (current != null)
{
temporaryQueue.add(current);
permanentQueue.add(current);
}
current = right;
if (current != null)
{
temporaryQueue.add(current);
permanentQueue.add(current);
}
}
}
return permanentQueue;
}
Upvotes: 2
Views: 7327
Reputation: 11
Here's a code I wrote to find the left view of a binary tree without recursion. Here I am keeping track of the number of nodes considering a null as a node in the tree istself. The number of null nodes for a null node in a paricular level will double up in the next level. The currNulls and nextNulls are keeping track of the nulls at the current and next level
void leftView(Node root){
if(root==null) return;
boolean newL=true;
int level=0,count=0,nextNulls=0,currNulls=0;
Queue<Node> q=new LinkedList<>();
q.add(root);
while(!q.isEmpty()){
Node node=q.remove();
if(newL){
System.out.print(node.data+" ");
newL=false;
}
count++;
if(node.left!=null){
q.add(node.left);
}
else{
nextNulls++;
}
if(node.right!=null){
q.add(node.right);
}
else{
nextNulls++;
}
if(1<<level == count+currNulls){
level++;
newL=true;
count=0;
// System.out.println("Curr -"+currNulls+"\tNext - "+nextNulls);
currNulls=nextNulls;
nextNulls=2*nextNulls;
}
}
}
Upvotes: 1
Reputation: 474
here's my javascript version of the level order traversal, which should point you in the right direction
I watched this video before writing this
var discovered = [];
var getLevels = function(node) {
if (node == null) { return []}
discovered.push(node)
var levels = levelOrderTraverse(discovered,[])
return levels
}
function levelOrderTraverse(discovered,elms) {
var level = []
for (var i = 0; i < discovered.length; i++) {
level.push(discovered[i].val)
}
elms.push(level);
var newlyDiscovered = [];
for (var i = 0; i < discovered.length; i++) {
if (discovered[i].left != null) {
newlyDiscovered.push(discovered[i].left)
}
if (discovered[i].right != null) {
newlyDiscovered.push(discovered[i].right)
}
}
if (newlyDiscovered.length > 0) {
levelOrderTraverse(newlyDiscovered,elms)
}
return elms
}
also can be found on my github with tests
Upvotes: 0
Reputation: 7183
It is possible to keep track of the level when you know that the number of nodes doubles each level. For example, in level 0, there is only 1 node; in level 1, there are 2 nodes; in level 2, there are 4 nodes; in level 3, there are 8 nodes; in level 4, there are 16 nodes; etc.
The code for grouping each level of nodes into an array using level-order traversal in Java may look like this:
private static Node[][] toArrayLevels(final Node node)
{
final Queue<Node> temporaryQueue = new LinkedList<Node>(); // Temporary queue is used for level-order traversal.
final ArrayList<Node[]> tree = new ArrayList<Node[]>(); // Levels containing their nodes.
ArrayList<Node> nodes = new ArrayList<Node>(); // Current level containing its nodes.
Node[][] treeArray = new Node[][]{};
Node[] nodesArray = new Node[]{};
Node current = node; // Level 0.
int level = 1; // Node's children are level 1.
temporaryQueue.add(current);
nodes.add(current);
tree.add(nodes.toArray(nodesArray));
nodes = new ArrayList<Node>(2);
while (!temporaryQueue.isEmpty())
{
// When the nodes completely fill the maximum spaces (2 ^ level) allowed on the current level, start the next level.
if (nodes.size() >= Math.pow(2, level))
{
tree.add(nodes.toArray(nodesArray));
nodes = new ArrayList<Node>((int) Math.pow(2, level));
level += 1;
}
current = temporaryQueue.remove();
// Check current's children.
if (current != null)
{
final Node left = current.getLeft();
final Node right = current.getRight();
temporaryQueue.add(left);
nodes.add(left);
temporaryQueue.add(right);
nodes.add(right);
}
else
{
// Null nodes fill spaces used to maintain the structural alignment of the tree.
nodes.add(null);
nodes.add(null);
}
}
// Push remaining nodes.
if (nodes.size() > 0)
{
tree.add(nodes.toArray(nodesArray));
}
return (tree.toArray(treeArray));
}
It checks the number of nodes on the current level. When the nodes have filled the current level, then it starts a new level.
As an example, a binary tree may look like this:
Level 0: 60
/ \
Level 1: 50 65
/ \ / \
Level 2: 49 55 -- 66
/ \ / \ / \ / \
Level 3: -- -- -- -- -- -- -- 71
Here is the output of the example:
System.out.println(Arrays.deepToString(binaryTree.toArrayLevels()));
[[{60}], [{50}, {65}], [{49}, {55}, null, {66}], [null, null, null, null, null, null, null, {71}], [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null]]
[
[{60}], // Level 0.
[{50}, {65}], // Level 1.
[{49}, {55}, null, {66}], // Level 2.
[null, null, null, null, null, null, null, {71}], // Level 3.
[null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null] // Level 4.
]
Here is the JavaScript version:
function toArrayLevels(node)
{
var temporary = []; // Temporary is used for level-order traversal.
var tree = []; // Levels containing their nodes.
var nodes = []; // Current level containing its nodes.
var current = node; // Level 0.
var level = 1; // Node's children are level 1.
temporary.push(current);
tree.push([current]);
while (temporary.length > 0)
{
// When the nodes completely fill the maximum spaces (2 ^ level) allowed on the current level, start the next level.
if (nodes.length >= Math.pow(2, level))
{
tree.push(nodes);
nodes = [];
level += 1;
}
current = temporary.shift();
// Check current's children.
if (current !== null)
{
var left = current.left;
var right = current.right;
temporary.push(left);
nodes.push(left);
temporary.push(right);
nodes.push(right);
}
else
{
// Null nodes fill spaces used to maintain the structural alignment of the tree.
nodes.push(null);
nodes.push(null);
}
}
// Push remaining nodes.
if (nodes.length > 0)
{
tree.push(nodes);
}
return tree;
}
Upvotes: 2
Reputation: 18747
public void bfs(Node root) {
Queue<Node> q = new LinkedList<Node>();
Node dummy = new Node(null);
q.add(root);
q.add(dummy);
while(!q.isEmpty()) {
Node curr = q.poll();
if(curr != null) {
System.out.print(curr.data + " ");
if(curr.left != null)
q.insert(curr.left);
if(curr.right !== null)
q.insert(curr.right);
} else {
System.out.println();
if(!q.isEmpty())
q.insert(dummy);
}
}
}
This code does not show the in-between null
nodes.
Upvotes: 3