Bird
Raised Fist0
DSA C++programming

BST Iterator Design in DSA C++

Choose your learning style10 modes available
Mental Model
A BST iterator lets you visit nodes in order one by one without storing all nodes at once. It uses a stack to remember where to go next.
Analogy: Imagine reading a book with bookmarks. You keep bookmarks on pages you might return to later, so you can continue reading in order without flipping all pages again.
      7
     / \
    3   15
       /  \
      9    20
Stack: Top -> [3,7] (nodes to visit next)
Current -> 3 (next smallest)
Dry Run Walkthrough
Input: BST: 7 -> 3, 15 -> 9, 20; iterate next 4 times
Goal: Visit nodes in ascending order: 3, 7, 9, 15
Step 1: Initialize iterator by pushing left nodes from root
Stack: Top -> [3,7]
Next node to visit is 3
Why: Start at smallest node by going left from root
Step 2: Pop 3 from stack and return it as next
Stack: Top -> [7]
Next node to visit is 7
Why: 3 has no left child, so we return it and move to next
Step 3: Pop 7 from stack and return it as next; push left nodes of 7's right child (15)
Stack: Top -> [9,15]
Next node to visit is 9
Why: After 7, go to right subtree starting at 15, push left nodes
Step 4: Pop 9 from stack and return it as next
Stack: Top -> [15]
Next node to visit is 15
Why: 9 has no left child, so return it and move on
Result:
3 -> 7 -> 9 -> 15 -> ...
Annotated Code
DSA C++
#include <iostream>
#include <stack>
using namespace std;

struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

class BSTIterator {
    stack<TreeNode*> stk;

    void pushLeft(TreeNode* node) {
        while (node) {
            stk.push(node); // remember node to visit later
            node = node->left; // go left to find smallest
        }
    }

public:
    BSTIterator(TreeNode* root) {
        pushLeft(root); // initialize stack with left path
    }

    bool hasNext() {
        return !stk.empty(); // if stack empty, no next
    }

    int next() {
        TreeNode* curr = stk.top();
        stk.pop(); // visit current smallest
        pushLeft(curr->right); // after visiting, push left path of right child
        return curr->val;
    }
};

int main() {
    TreeNode* root = new TreeNode(7);
    root->left = new TreeNode(3);
    root->right = new TreeNode(15);
    root->right->left = new TreeNode(9);
    root->right->right = new TreeNode(20);

    BSTIterator it(root);
    while (it.hasNext()) {
        cout << it.next() << " -> ";
    }
    cout << "null" << endl;
    return 0;
}
while (node) { stk.push(node); node = node->left; }
push all left children to stack to reach smallest node
TreeNode* curr = stk.top(); stk.pop();
pop top node as next smallest to return
pushLeft(curr->right);
after visiting node, push left path of its right subtree
return curr->val;
return current node's value as next in order
OutputSuccess
3 -> 7 -> 9 -> 15 -> 20 -> null
Complexity Analysis
Time: O(1) amortized per next() call because each node is pushed and popped once
Space: O(h) where h is tree height, due to stack storing left path nodes
vs Alternative: Compared to storing all nodes in an array (O(n) space), this uses less memory and supports lazy iteration
Edge Cases
Empty tree
hasNext() returns false immediately, no next() calls possible
DSA C++
return !stk.empty();
Tree with single node
next() returns that node value once, then hasNext() false
DSA C++
while (node) { stk.push(node); node = node->left; }
Right skewed tree (all right children)
stack holds only one node at a time, iteration proceeds linearly
DSA C++
pushLeft(curr->right);
When to Use This Pattern
When you need to iterate a BST in sorted order without extra space for all nodes, use a stack-based iterator to simulate in-order traversal lazily.
Common Mistakes
Mistake: Pushing all nodes into a list at once instead of using a stack for lazy traversal
Fix: Use a stack to push only left children and push right subtree nodes on demand
Mistake: Not pushing left children of the right subtree after popping a node
Fix: After popping a node, call pushLeft on its right child to continue in-order
Summary
It lets you visit BST nodes in ascending order one by one using a stack.
Use it when you want sorted traversal without storing all nodes at once.
The key is to push left children on stack and after visiting a node, push left path of its right child.

Practice

(1/5)
1. What is the main purpose of a BST Iterator in the context of a Binary Search Tree?
easy
A. To traverse the BST in ascending order without recursion
B. To insert new nodes into the BST
C. To delete nodes from the BST
D. To balance the BST automatically

Solution

  1. Step 1: Understand BST Iterator functionality

    A BST Iterator is designed to traverse the tree in sorted order, typically ascending, without using recursion explicitly.
  2. Step 2: Identify the main purpose

    It provides a way to get the next smallest element efficiently, which matches To traverse the BST in ascending order without recursion.
  3. Final Answer:

    To traverse the BST in ascending order without recursion -> Option A
  4. Quick Check:

    BST Iterator = In-order traversal without recursion [OK]
Hint: BST Iterator returns next smallest element in sorted order [OK]
Common Mistakes:
  • Confusing iterator with insertion or deletion operations
  • Thinking it balances the tree automatically
  • Assuming it uses recursion internally
2. Which of the following is the correct way to declare a stack to be used in a BST Iterator in C++?
easy
A. stack s;
B. stack<int> s;
C. stack<TreeNode> s;
D. stack s;

Solution

  1. Step 1: Identify the data type stored in the stack

    The BST Iterator stores pointers to tree nodes to traverse the tree efficiently, so the stack should hold TreeNode pointers.
  2. Step 2: Match the correct syntax

    stack s; uses stack which is correct. stack<int> s; uses int, which is incorrect. stack<TreeNode> s; uses TreeNode by value, which is inefficient. stack s; uses Node*, which is undefined here.
  3. Final Answer:

    stack s; -> Option D
  4. Quick Check:

    Stack stores pointers to TreeNode [OK]
Hint: Stack must hold pointers to tree nodes, not values [OK]
Common Mistakes:
  • Using stack of int instead of TreeNode*
  • Using stack of TreeNode by value causing copies
  • Using undefined Node* type
3. Given the following BST Iterator code snippet, what will be the output sequence of calls to next()?
struct TreeNode {
  int val;
  TreeNode* left;
  TreeNode* right;
  TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

class BSTIterator {
  stack s;
  void pushLeft(TreeNode* node) {
    while (node) {
      s.push(node);
      node = node->left;
    }
  }
public:
  BSTIterator(TreeNode* root) { pushLeft(root); }
  int next() {
    TreeNode* node = s.top(); s.pop();
    pushLeft(node->right);
    return node->val;
  }
  bool hasNext() { return !s.empty(); }
};

// BST structure:
//       7
//      / \
//     3   15
//         / \
//        9  20

BSTIterator it(root);
while(it.hasNext()) {
  cout << it.next() << " ";
}
medium
A. 20 15 9 7 3
B. 7 3 15 9 20
C. 3 7 9 15 20
D. 3 9 7 15 20

Solution

  1. Step 1: Understand the BST structure and in-order traversal

    The BST is: 7 / \ 3 15 / \ 9 20 In-order traversal visits nodes in ascending order: 3, 7, 9, 15, 20.
  2. Step 2: Trace the iterator's next() calls

    Iterator pushes left nodes first, so initial stack: 7, 3 (top). Calls to next() pop 3, then 7, then push left of 7's right (15), then 9, then 15, then 20. Output sequence matches 3 7 9 15 20.
  3. Final Answer:

    3 7 9 15 20 -> Option C
  4. Quick Check:

    In-order traversal = 3 7 9 15 20 [OK]
Hint: BST Iterator outputs nodes in ascending order (in-order) [OK]
Common Mistakes:
  • Confusing pre-order or post-order traversal output
  • Not pushing left children correctly
  • Misunderstanding stack top element order
4. Identify the bug in the following BST Iterator next() method and select the correct fix:
int next() {
  TreeNode* node = s.top();
  s.pop();
  pushLeft(node->left); // Bug here
  return node->val;
}
medium
A. Remove pushLeft call completely
B. Change pushLeft(node->left) to pushLeft(node->right)
C. Change s.pop() to s.pop(node)
D. Add check if node is nullptr before pushLeft

Solution

  1. Step 1: Analyze the next() method logic

    After popping the current node, the iterator should push all left children of the right subtree to continue in-order traversal.
  2. Step 2: Identify the incorrect call

    The code incorrectly calls pushLeft(node->left), which revisits the left subtree already processed. It should call pushLeft(node->right) to process the right subtree.
  3. Final Answer:

    Change pushLeft(node->left) to pushLeft(node->right) -> Option B
  4. Quick Check:

    Push left of right subtree after pop [OK]
Hint: Push left nodes of right child after popping [OK]
Common Mistakes:
  • Pushing left subtree again causing infinite loop
  • Removing pushLeft call causing incomplete traversal
  • Incorrect pop syntax causing compile error
5. You want to design a BST Iterator that supports a method peek() which returns the next smallest element without advancing the iterator. How would you modify the existing BST Iterator design to support peek() efficiently?
hard
A. Store the next smallest element in a variable during next() and return it in peek()
B. Use an additional stack to store peeked elements separately
C. Modify next() to not pop from stack and peek() to pop instead
D. Precompute all elements in sorted order and store in a vector

Solution

  1. Step 1: Understand peek() requirement

    peek() should return next smallest element without moving the iterator forward, so it must remember the next element.
  2. Step 2: Modify iterator to store next element

    By storing the next smallest element in a variable during next(), peek() can return this stored value without popping or changing the stack.
  3. Step 3: Evaluate other options

    Using an extra stack or precomputing all elements wastes space or changes iterator behavior. Modifying next() to not pop breaks standard iteration.
  4. Final Answer:

    Store the next smallest element in a variable during next() and return it in peek() -> Option A
  5. Quick Check:

    Cache next element for peek() [OK]
Hint: Cache next element on next() call for peek() [OK]
Common Mistakes:
  • Precomputing all elements wastes memory
  • Changing next() behavior breaks iteration
  • Using extra stack complicates design unnecessarily
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard