Skip to content
DSA trees 7 min read

Binary Search Trees (BST): The Ordering Property

A binary search tree (BST) is a binary tree with one extra rule, the BST property: for every node, all values in its left subtree are smaller and all values in its right subtree are larger. That single invariant turns a tree into a searchable structure where you can find, insert, or delete a value in O(h) time — O(log n) when the tree is balanced.

We reuse the standard TreeNode.

The BST property, precisely

For a node with value v:

  • Every value in the left subtree is < v.
  • Every value in the right subtree is > v.
  • Both subtrees are themselves BSTs.

This must hold for every node, not just the root — a subtle point that trips people up.

            (8)
           /   \
        (3)     (10)
        /  \        \
     (1)   (6)      (14)
           /  \      /
        (4)   (7)  (13)

Searching is like binary search on an array: compare with the current node, then go left or right, halving the remaining tree each step.

Why in-order traversal gives sorted output

This is the BST’s signature property. An in-order traversal visits left, then node, then right. Because everything left of a node is smaller and everything right is larger, processing the node between its subtrees emits values in ascending order.

For the tree above, in-order yields: 1 3 4 6 7 8 10 13 14 — fully sorted.

void inorder(TreeNode* root, std::vector<int>& out) {
    if (root == nullptr) return;
    inorder(root->left, out);   // smaller values first
    out.push_back(root->val);   // then this node
    inorder(root->right, out);  // then larger values
}

For beginners: This gives a neat way to check whether a tree is a valid BST — run an in-order traversal and confirm the output is strictly increasing.

Validating a BST correctly

A common bug is checking only node.left.val < node.val < node.right.val locally. That misses violations deeper down. The robust approach passes a valid (low, high) range down the recursion:

bool isBST(TreeNode* node, long low, long high) {
    if (node == nullptr) return true;
    if (node->val <= low || node->val >= high) return false;
    return isBST(node->left, low, node->val) &&
           isBST(node->right, node->val, high);
}
// call: isBST(root, LONG_MIN, LONG_MAX)

Both the in-order walk and the range check run in O(n) time and O(h) space.

Complexity & the balance caveat

OperationAverageWorst (skewed)
Search / insert / deleteO(log n)O(n)

The O(log n) promise only holds when the tree stays roughly balanced. Inserting already-sorted data into a plain BST produces a degenerate, linked-list-shaped tree with O(n) operations. The fix is self-balancing trees.

Going deeper: AVL and red-black trees restructure themselves on every insert/delete to guarantee O(log n) height no matter the input order.

Next steps

See the BST property in action with BST operations — search, insert, and delete — then keep it efficient with balanced trees & AVL.

Last updated June 25, 2026
Was this helpful?