Given a Binary Tree, the task is to print the nodes level-wise, each level on a new line.
Example:
Input:
Output:
1
2 3
4 5
Try It Yourself
Table of Content
[Naive Approach] Using Recursion - O(n^2) Time and O(n) Space
- Compute Height of the Tree
- Print nodes of every level from 1 to height by calling a function with given level
- A recursive function is used to print nodes at a given level where we pass level - 1 in the recursive calls and the base case is to print the node when level is 1.
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node *left, *right;
Node(int key) {
data = key;
left = nullptr;
right = nullptr;
}
};
// Print nodes at a given level
void printLevel(Node *root, int level, vector<int> &levelNodes) {
if (root == nullptr)
return;
if (level == 1) {
levelNodes.push_back(root->data);
}
else if (level > 1) {
printLevel(root->left, level - 1, levelNodes);
printLevel(root->right, level - 1, levelNodes);
}
}
// Compute the "height" of a tree -- the number of
// nodes along the longest path from the root node
// down to the farthest leaf node.
int height(Node *node) {
if (node == nullptr)
return 0;
// Compute the height of each subtree
int lheight = height(node->left);
int rheight = height(node->right);
// Use the larger one without the ternary operator
if (lheight > rheight) {
return lheight + 1;
}
else {
return rheight + 1;
}
}
// Function to return level order traversal as
// a vector of vectors
vector<vector<int>> levelOrder(Node *root) {
vector<vector<int>> result;
int h = height(root);
for (int i = 1; i <= h; i++) {
vector<int> levelNodes;
printLevel(root, i, levelNodes);
result.push_back(levelNodes);
}
return result;
}
int main() {
// Binary Tree Representation
//
// 1
// / \
// 2 3
// / \
// 4 5
Node *root = new Node(1);
root->left = new Node(2);
root->right = new Node(3);
root->left->left = new Node(4);
root->left->right = new Node(5);
vector<vector<int>> result = levelOrder(root);
for (const auto &level : result) {
for (int val : level) {
cout << val << " ";
}
cout << endl;
}
return 0;
}
import java.util.ArrayList;
import java.util.List;
class Node {
int data;
Node left, right;
Node(int key) {
data = key;
left = null;
right = null;
}
}
class GfG {
// Compute the "height" of a tree -- the number of
// nodes along the longest path from the root node
// down to the farthest leaf node.
static int height(Node node) {
if (node == null)
return 0;
else {
// compute the height of each subtree
int lheight = height(node.left);
int rheight = height(node.right);
// use the larger one
return Math.max(lheight, rheight) + 1;
}
}
static void printLevel(Node root, int level,
List<Integer> levelNodes) {
if (root == null)
return;
if (level == 1)
levelNodes.add(root.data);
else if (level > 1) {
printLevel(root.left, level - 1, levelNodes);
printLevel(root.right, level - 1, levelNodes);
}
}
// Function to return level order traversal as a list of
// lists
static List<List<Integer> > levelOrder(Node root) {
List<List<Integer> > result = new ArrayList<>();
int h = height(root);
for (int i = 1; i <= h; i++) {
List<Integer> levelNodes = new ArrayList<>();
printLevel(root, i, levelNodes);
result.add(levelNodes);
}
return result;
}
public static void main(String[] args) {
// Binary Tree Representation
//
// 1
// / \
// 2 3
// / \
// 4 5
Node root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
List<List<Integer> > result = levelOrder(root);
for (List<Integer> level : result) {
for (int val : level) {
System.out.print(val + " ");
}
System.out.println();
}
}
}
class Node:
def __init__(self, key):
self.data = key
self.left = None
self.right = None
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
return (lheight + 1) if lheight > rheight else (rheight + 1)
def printLevel(root, level, levelNodes):
if root is None:
return
if level == 1:
levelNodes.append(root.data)
elif level > 1:
printLevel(root.left, level - 1, levelNodes)
printLevel(root.right, level - 1, levelNodes)
def levelOrder(root):
result = []
h = height(root)
for i in range(1, h + 1):
levelNodes = []
printLevel(root, i, levelNodes)
result.append(levelNodes)
return result
# Binary Tree Representation
#
# 1
# / \
# 2 3
# / \
# 4 5
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)
result = levelOrder(root)
for level in result:
for val in level:
print(val, end=" ")
print()
using System;
using System.Collections.Generic;
class Node {
public int data;
public Node left, right;
public Node(int key) {
data = key;
left = null;
right = null;
}
}
class GfG {
// Compute the "height" of a tree -- the number of
// nodes along the longest path from the root node
// down to the farthest leaf node.
static int Height(Node node) {
if (node == null)
return 0;
else {
// compute the height of each subtree
int lheight = Height(node.left);
int rheight = Height(node.right);
// use the larger one
return Math.Max(lheight, rheight) + 1;
}
}
static void PrintLevel(Node root, int level,
List<int> levelNodes) {
if (root == null)
return;
if (level == 1)
levelNodes.Add(root.data);
else if (level > 1) {
PrintLevel(root.left, level - 1, levelNodes);
PrintLevel(root.right, level - 1, levelNodes);
}
}
// Function to return level order traversal
// as a list of lists
static List<List<int>> LevelOrder(Node root) {
List<List<int>> result = new List<List<int>>();
int h = Height(root);
for (int i = 1; i <= h; i++) {
List<int> levelNodes = new List<int>();
PrintLevel(root, i, levelNodes);
result.Add(levelNodes);
}
return result;
}
static void Main() {
// Binary Tree Representation
//
// 1
// / \
// 2 3
// / \
// 4 5
Node root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
List<List<int>> result = LevelOrder(root);
foreach (var level in result) {
foreach (var val in level) {
Console.Write(val + " ");
}
Console.WriteLine();
}
}
}
class Node {
constructor(key) {
this.data = key;
this.left = null;
this.right = null;
}
}
function height(node) {
if (node === null) {
return 0;
} else {
// compute the height of each subtree
const lheight = height(node.left);
const rheight = height(node.right);
// use the larger one
return Math.max(lheight, rheight) + 1;
}
}
function printLevel(root, level, levelNodes) {
if (root === null) {
return;
}
if (level === 1) {
levelNodes.push(root.data);
} else if (level > 1) {
printLevel(root.left, level - 1, levelNodes);
printLevel(root.right, level - 1, levelNodes);
}
}
function levelOrder(root) {
const result = [];
const h = height(root);
for (let i = 1; i <= h; i++) {
const levelNodes = [];
printLevel(root, i, levelNodes);
result.push(levelNodes);
}
return result;
}
// Binary Tree Representation
//
// 1
// / \
// 2 3
// / \
// 4 5
// driver code
const root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
const traversal = levelOrder(root);
for (const level of traversal) {
console.log(level.join(" "));
}
Output
1 2 3 4 5
[Expected Approach] Using Queue – O(n) Time and O(n) Space
- If we take a closer look at the working of standard level order traversal, we can notice that after processing a every iteration, we have the nodes of the next level in the queue. Why? because when we do level order traversal, we push children of the current node after processing it.
- Before beginning the standard queue based loop, we get the size of the queue to count the number of nodes and then run a loop to print those many nodes followed by a newline.
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node* left;
Node* right;
Node(int val) {
data = val;
left = nullptr;
right = nullptr;
}
};
// Function to do level order traversal and return a 2D vector
vector<vector<int>> levelOrder(Node* root) {
vector<vector<int>> result;
if (root == nullptr)
return result;
// Create an empty queue for level order traversal
queue<Node*> q;
q.push(root);
while (!q.empty()) {
// nodeCount (queue size) indicates number of
// nodes at current level.
int nodeCount = q.size();
vector<int> currentLevel;
for(int i = 0; i < nodeCount; i++) {
Node* node = q.front();
q.pop();
currentLevel.push_back(node->data);
if (node->left != nullptr)
q.push(node->left);
if (node->right != nullptr)
q.push(node->right);
}
result.push_back(currentLevel);
}
return result;
}
int main() {
// Binary tree structure:
//
// 1
// / \
// 2 3
// / \
// 4 5
Node* root = new Node(1);
root->left = new Node(2);
root->right = new Node(3);
root->left->left = new Node(4);
root->left->right = new Node(5);
vector<vector<int>> traversal = levelOrder(root);
for (const auto& level : traversal) {
for (int val : level) {
cout << val << " ";
}
cout << endl;
}
return 0;
}
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
class Node {
int data;
Node left, right;
Node(int val) {
data = val;
left = null;
right = null;
}
}
class GfG {
// Function to do level order traversal and return a 2D list
static ArrayList<ArrayList<Integer>> levelOrder(Node root) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
if (root == null) return result;
// Create an empty queue for level order traversal
Queue<Node> q = new LinkedList<>();
q.add(root);
while (!q.isEmpty()) {
// nodeCount (queue size) indicates number of
// nodes at current level.
int nodeCount = q.size();
ArrayList<Integer> currentLevel = new ArrayList<>();
for(int i = 0; i < nodeCount; i++) {
Node node = q.poll();
currentLevel.add(node.data);
if (node.left != null) q.add(node.left);
if (node.right != null) q.add(node.right);
}
result.add(currentLevel);
}
return result;
}
public static void main(String[] args) {
// Binary tree structure:
//
// 1
// / \
// 2 3
// / \
// 4 5
//
Node root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
ArrayList<ArrayList<Integer>> traversal = levelOrder(root);
for (ArrayList<Integer> level : traversal) {
for (int val : level) {
System.out.print(val + " ");
}
System.out.println();
}
}
}
class Node:
def __init__(self, val):
self.data = val
self.left = None
self.right = None
# Function to do level order traversal
# and return a 2D list
def levelOrder(root):
result = []
if root is None:
return result
# Create an empty queue for level order traversal
q = [root]
while q:
# nodeCount (queue size) indicates number
# of nodes at current level.
nodeCount = len(q)
currentLevel = []
for i in range(nodeCount):
node = q.pop(0)
currentLevel.append(node.data)
if node.left is not None:
q.append(node.left)
if node.right is not None:
q.append(node.right)
result.append(currentLevel)
return result
if __name__ == "__main__":
# Binary tree structure:
#
# 1
# / \
# 2 3
# / \
# 4 5
#
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)
traversal = levelOrder(root)
for level in traversal:
for val in level:
print(val, end=" ")
print()
using System;
using System.Collections.Generic;
class Node {
public int data;
public Node left, right;
public Node(int val) {
data = val;
left = null;
right = null;
}
}
class GfG {
// Function to do level order traversal and return a 2D list
static List<List<int>> LevelOrder(Node root) {
List<List<int>> result = new List<List<int>>();
if (root == null) return result;
// Create an empty queue for level order traversal
Queue<Node> queue = new Queue<Node>();
queue.Enqueue(root);
while (queue.Count > 0) {
// nodeCount (queue size) indicates number of
// nodes at current level.
int nodeCount = queue.Count;
List<int> currentLevel = new List<int>();
for(int i = 0; i < nodeCount; i++) {
Node node = queue.Dequeue();
currentLevel.Add(node.data);
if (node.left != null) queue.Enqueue(node.left);
if (node.right != null) queue.Enqueue(node.right);
}
result.Add(currentLevel);
}
return result;
}
static void Main(string[] args) {
// Binary tree structure:
//
// 1
// / \
// 2 3
// / \
// 4 5
Node root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
List<List<int>> traversal = LevelOrder(root);
foreach (List<int> level in traversal) {
foreach (int val in level) {
Console.Write(val + " ");
}
Console.WriteLine();
}
}
}
class Node {
constructor(val) {
this.data = val;
this.left = null;
this.right = null;
}
}
// Function to do level order traversal and return a 2D array
function levelOrder(root) {
const result = [];
if (root === null) return result;
// Create an empty queue for level order traversal
const q = [root];
while (q.length > 0) {
// nodeCount (queue size) indicates number
// of nodes at current level.
const nodeCount = q.length;
const currentLevel = [];
for (let i = 0; i < nodeCount; i++) {
const node = q.shift();
currentLevel.push(node.data);
if (node.left !== null) q.push(node.left);
if (node.right !== null) q.push(node.right);
}
result.push(currentLevel);
}
return result;
}
// Binary tree structure:
// 1
// / \
// 2 3
// / \
// 4 5
const root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
const traversal = levelOrder(root);
for (const level of traversal) {
console.log(level.join(" "));
}
Output
1 2 3 4 5
Related articles:
