Skip to content
Home DSA Convert BST to Sorted Array — In-Order Traversal

Convert BST to Sorted Array — In-Order Traversal

Where developers are forged. · Structured learning · Free forever.
📍 Part of: Trees → Topic 13 of 15
Learn how in-order traversal of a Binary Search Tree produces a sorted array, and how to reconstruct a BST from a sorted array in O(n) time.
⚙️ Intermediate — basic DSA knowledge assumed
In this tutorial, you'll learn
Learn how in-order traversal of a Binary Search Tree produces a sorted array, and how to reconstruct a BST from a sorted array in O(n) time.
  • In-order traversal of a BST produces elements in sorted ascending order.
  • A balanced BST from a sorted array is built by recursively choosing the middle element as root.
  • Both conversions run in O(n) time.
✦ Plain-English analogy ✦ Real code with output ✦ Interview questions
Quick Answer

Imagine a library where books are shelved in a special way: every book on the left shelf is alphabetically earlier than the current book, and every book on the right shelf comes after it. If you walk through that library always going left first, then reading the current book, then going right — you'll read every book in perfect alphabetical order without any sorting effort. A Binary Search Tree (BST) is that library, and in-order traversal is that exact walking pattern. Converting a BST to a sorted array is just writing down the titles as you walk.

Sorted data is the foundation of fast searching, clean output, and reliable comparisons. But in the real world, data rarely arrives pre-sorted in an array — it's often stored in a BST because insertion and lookup are O(log n). When you need to export that data, merge it with another dataset, or display it to a user, you need a flat, sorted list. Knowing how to flatten a BST into a sorted array efficiently is a skill that shows up everywhere from database query engines to autocomplete systems.

The problem this solves is deceptively simple to state but easy to get wrong: given the root of a BST, produce an array where every element is in ascending order. The naive approach — dump all nodes into an array and call Arrays.sort() — works but wastes the BST's built-in ordering guarantee entirely. The smart approach exploits the BST property directly, giving you a sorted array in O(n) time with zero comparisons.

By the end of this article you'll understand exactly why in-order traversal produces sorted output (not just that it does), you'll have two complete runnable implementations (recursive and iterative), you'll know the three most common mistakes developers make, and you'll be ready to field the interview questions that trip people up most.

What is Convert BST to Sorted Array? — Plain English

A Binary Search Tree (BST) has a fundamental property: for any node, all values in its left subtree are smaller, and all values in its right subtree are larger. In-order traversal (left → root → right) of a BST visits nodes in ascending sorted order. This means converting a BST to a sorted array is as simple as performing an in-order traversal and collecting node values. The reverse direction — converting a sorted array to a height-balanced BST — works by always picking the middle element of the current subarray as the root, then recursively building the left subtree from the left half and right subtree from the right half. This ensures the tree is balanced because both halves have roughly equal size.

How the Conversion Works — Step by Step

BST to sorted array via in-order traversal: 1. If current node is None, return. 2. Recursively traverse left subtree. 3. Append current node's value to result. 4. Recursively traverse right subtree. 5. The result list is sorted because BST property guarantees left < root < right.

Sorted array to balanced BST: 1. If array is empty, return None. 2. Find mid = len(array) // 2. 3. Create a TreeNode with value array[mid]. 4. node.left = recursively build from array[:mid]. 5. node.right = recursively build from array[mid+1:]. 6. Return node.

For array [1,2,3,4,5,6,7]: mid=3 (value 4) becomes root. Left subtree from [1,2,3]: mid=1 (value 2). Right subtree from [5,6,7]: mid=1 (value 6). This produces a perfectly balanced BST of height 2.

Worked Example — Tracing Both Directions

BST: 4 / \ 2 6 / \ / \ 1 3 5 7

In-order traversal → sorted array: 1. Go left from 4 to 2. Go left from 2 to 1. 1 has no children → append 1. 2. Back to 2 → append 2. Go right to 3 → append 3. 3. Back to 4 → append 4. Go right to 6. 4. Go left from 6 to 5 → append 5. Back to 6 → append 6. Right to 7 → append 7. 5. Result: [1,2,3,4,5,6,7].

Now reverse: sorted [1,2,3,4,5,6,7] → BST: - mid=3 → root=4. Left from [1,2,3]: mid=1 → root=2, left=1, right=3. - Right from [5,6,7]: mid=1 → root=6, left=5, right=7. - Tree is exactly the original BST above. Height = 2, perfectly balanced.

Implementation

Both directions are clean recursive implementations. BST to array uses in-order DFS. Array to BST uses divide-and-conquer, always picking the midpoint as root. The BST-to-array runs in O(n) time and O(n) space (result + call stack). The array-to-BST also runs in O(n) time and O(log n) stack space for a balanced input. An iterative in-order traversal using an explicit stack avoids recursion depth issues for very deep trees.

bst_sorted_array.py · PYTHON
12345678910111213141516171819202122232425262728293031323334353637
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val; self.left = left; self.right = right

def bst_to_sorted_array(root):
    """In-order traversal → sorted list."""
    result = []
    def inorder(node):
        if not node:
            return
        inorder(node.left)
        result.append(node.val)
        inorder(node.right)
    inorder(root)
    return result

def sorted_array_to_bst(nums):
    """Sorted array → height-balanced BST."""
    if not nums:
        return None
    mid = len(nums) // 2
    node = TreeNode(nums[mid])
    node.left = sorted_array_to_bst(nums[:mid])
    node.right = sorted_array_to_bst(nums[mid+1:])
    return node

# Build BST manually and convert
root = TreeNode(4)
root.left = TreeNode(2, TreeNode(1), TreeNode(3))
root.right = TreeNode(6, TreeNode(5), TreeNode(7))

arr = bst_to_sorted_array(root)
print(arr)  # [1, 2, 3, 4, 5, 6, 7]

# Rebuild BST from sorted array
new_root = sorted_array_to_bst(arr)
print(bst_to_sorted_array(new_root))  # [1, 2, 3, 4, 5, 6, 7]
▶ Output
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7]
AspectRecursive In-OrderIterative In-Order
Code readabilityVery clean — mirrors the definition directlyMore verbose — explicit stack management
Risk of StackOverflowYes — on degenerate trees (height = n)No — uses heap-allocated Deque instead
Space complexity (extra)O(h) implicit call stack; O(n) worst caseO(h) explicit Deque; O(n) worst case
Time complexityO(n) — visits each node onceO(n) — visits each node once
Best forBalanced trees, interviews, prototypingProduction code, unknown input distributions
DebuggabilityHarder — stack frames aren't directly inspectableEasier — you can inspect the Deque at any point
Tail-call optimizationJava does NOT optimize tail calls — no benefit hereN/A — no recursion to optimize

🎯 Key Takeaways

  • In-order traversal of a BST produces elements in sorted ascending order.
  • A balanced BST from a sorted array is built by recursively choosing the middle element as root.
  • Both conversions run in O(n) time.

⚠ Common Mistakes to Avoid

    Building the BST from already-sorted input and expecting it to be balanced — The tree degenerates into a right-skewed linked list (height = n), making traversal O(n) stack depth and causing StackOverflowError on large inputs — Fix: shuffle input before building, use an iterative traversal, or use a self-balancing structure like Java's TreeMap.
    Fix

    shuffle input before building, use an iterative traversal, or use a self-balancing structure like Java's TreeMap.

    Using a List<Integer> index manually inside the recursive method without a mutable wrapper — You try to pass an int index into the recursive helper, increment it, and find the outer method still sees index = 0 because primitives are passed by value in Java — Fix: wrap the index in an int[] of size 1 (e.g., int[] idx = {0}) or use a class-level field, so the recursive calls share the same mutable reference.
    Fix

    wrap the index in an int[] of size 1 (e.g., int[] idx = {0}) or use a class-level field, so the recursive calls share the same mutable reference.

    Forgetting to handle duplicate values consistently — If you insert duplicates (e.g., 30, 30) without a clear rule (always left, always right, or discard), your BST property becomes ambiguous and the sorted output may have unexpected ordering — Fix: decide on a deduplication or placement strategy at insertion time: use value < root.value for strict left placement of duplicates, or add a count field to each node and skip duplicate nodes in the output.
    Fix

    decide on a deduplication or placement strategy at insertion time: use value < root.value for strict left placement of duplicates, or add a count field to each node and skip duplicate nodes in the output.

Interview Questions on This Topic

  • QWhat traversal gives sorted output from a BST?
  • QHow do you build a balanced BST from a sorted array?
  • QWhy is the middle element chosen as the root?

Frequently Asked Questions

Why does in-order traversal of a BST give sorted output?

The BST invariant guarantees every node in the left subtree is smaller than the current node, which is smaller than every node in the right subtree. In-order visits left first (all smaller), then root, then right (all larger). This recursive structure produces sorted order at every level.

How do you verify a BST is valid after construction?

Perform in-order traversal and check that the output is strictly increasing. Alternatively, validate recursively by passing min and max bounds: each node must be within (min_val, max_val), and recursive calls tighten the bounds — the right subtree's min is set to the current node's value.

What is the height of a BST built from a sorted array of n elements?

The divide-and-conquer approach always splits the array in half, producing a height of floor(log2(n)). For n=7: height=2. For n=15: height=3. This is optimal — no BST with n nodes can have height less than floor(log2(n)).

🔥
Naren Founder & Author

Developer and founder of TheCodeForge. I built this site because I was tired of tutorials that explain what to type without explaining why it works. Every article here is written to make concepts actually click.

← PreviousDiameter of Binary TreeNext →Serialize and Deserialize Binary Tree
Forged with 🔥 at TheCodeForge.io — Where Developers Are Forged