Tree Traversal Level Order BFS in DSA C++ - Time & Space Complexity
We want to understand how long it takes to visit all nodes in a tree using level order traversal.
How does the time grow as the tree gets bigger?
Analyze the time complexity of the following code snippet.
void levelOrderTraversal(TreeNode* root) {
if (!root) return;
std::queue q;
q.push(root);
while (!q.empty()) {
TreeNode* node = q.front();
q.pop();
// process node->val
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
}
This code visits every node in the tree level by level, from top to bottom and left to right.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Visiting each node once inside the while loop.
- How many times: Exactly once for each node in the tree.
As the number of nodes grows, the number of visits grows the same way.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 visits |
| 100 | About 100 visits |
| 1000 | About 1000 visits |
Pattern observation: The operations grow directly with the number of nodes.
Time Complexity: O(n)
This means the time to finish grows linearly with the number of nodes in the tree.
[X] Wrong: "Level order traversal takes more than linear time because it uses a queue and loops inside loops."
[OK] Correct: Each node is added and removed from the queue exactly once, so the total work is proportional to the number of nodes, not more.
Understanding level order traversal time helps you explain how breadth-first search works efficiently on trees and graphs.
"What if the tree is very unbalanced and looks like a linked list? How would the time complexity change?"
Practice
Solution
Step 1: Understand Level Order Traversal
Level order traversal visits nodes level by level starting from the root, moving left to right on each level.Step 2: Compare with other traversals
Preorder, inorder, and postorder are depth-first traversals, not level by level.Final Answer:
Visits nodes level by level from top to bottom, left to right -> Option AQuick Check:
Level order = BFS = top to bottom, left to right [OK]
- Confusing level order with preorder traversal
- Thinking level order is depth-first
- Mixing up traversal orders
Solution
Step 1: Understand queue declaration for pointers
We need a queue that stores pointers to TreeNode objects, so use queue.Step 2: Check other options
queue<TreeNode> stores objects, not pointers; queue is invalid syntax; queue is invalid for queue.Final Answer:
queue q; -> Option BQuick Check:
Queue of pointers = queue [OK]
- Using queue<TreeNode> instead of queue
- Trying to use references in queue declaration
- Incorrect syntax with array brackets
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
// Tree structure:
// 1
// / \
// 2 3
// / / \
// 4 5 6
TreeNode* root = new TreeNode(1);
root->left = new TreeNode(2);
root->right = new TreeNode(3);
root->left->left = new TreeNode(4);
root->right->left = new TreeNode(5);
root->right->right = new TreeNode(6);
queue q;
q.push(root);
while (!q.empty()) {
TreeNode* node = q.front(); q.pop();
cout << node->val << " ";
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}Solution
Step 1: Trace the queue operations
Start with root (1). Queue: [1]. Output: "". Pop 1, output "1 ". Push 2 and 3. Queue: [2,3]. Pop 2, output "2 ". Push 4. Queue: [3,4]. Pop 3, output "3 ". Push 5 and 6. Queue: [4,5,6]. Pop 4, output "4 ". No children. Queue: [5,6]. Pop 5, output "5 ". No children. Queue: [6]. Pop 6, output "6 ". No children. Queue empty.Step 2: Combine outputs
Concatenate outputs: 1 2 3 4 5 6Final Answer:
1 2 3 4 5 6 -> Option DQuick Check:
Level order traversal output = 1 2 3 4 5 6 [OK]
- Mixing left and right child order
- Confusing preorder with level order output
- Forgetting to push children in correct order
void levelOrder(TreeNode* root) {
queue q;
q.push(root);
while (!q.empty()) {
TreeNode* node = q.front();
cout << node->val << " ";
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
}Solution
Step 1: Analyze the while loop
The code pushes root, then loops while queue not empty. It gets front node but never removes it with q.pop(), causing infinite loop.Step 2: Identify fix
Adding q.pop() after processing node removes it from queue, allowing loop to progress.Final Answer:
Missing q.pop() inside the while loop -> Option AQuick Check:
Queue pop missing causes infinite loop [OK]
- Forgetting to pop queue front
- Using stack instead of queue for BFS
- Not checking for nullptr root before pushing
vector levelOrder(TreeNode* root) {
vector result;
if (!root) return result;
queue q;
q.push(root);
while (!q.empty()) {
int size = q.size();
vector<int> level;
for (int i = 0; i < size; i++) {
TreeNode* node = q.front(); q.pop();
level.push_back(node->val);
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
result.push_back(level);
}
return result;
}Solution
Step 1: Understand level grouping in BFS
Using the queue size at each iteration lets us process all nodes at the current level before moving to the next.Step 2: Evaluate other options
Stack is LIFO, not suitable for level order. Recursion can do level grouping but is not BFS. Inorder traversal does not group by levels.Final Answer:
Use a loop over current queue size to separate levels -> Option CQuick Check:
Queue size loop separates levels in BFS [OK]
- Using stack instead of queue for level order
- Trying inorder traversal for level grouping
- Ignoring queue size to separate levels
Ready to prove it?
Pass the test and this pattern moves unknown
