Algorithms · Data Structures

Balance by Chance.

A plain binary search tree can degrade to a O(n) chain if keys arrive in sorted order. Balanced trees like AVL and red-black fix this with intricate rebalancing rules. A treap takes a wonderfully lazy shortcut: give every node a random priority and require the tree to be a heap on those priorities as well as a BST on the keys (hence tree + heap = “treap”). Because the shape is now determined by the random priorities — not by the order keys were inserted — the tree is balanced in expectation, with height O(log n), using only simple rotations. Insert keys and watch random priorities rotate the tree into balance.

O(log n) expected height · BST on keys + max-heap on random priorities · rotations only
BST property

Keys obey binary-search order: left subtree < node < right subtree.

heap property

Priorities obey a max-heap: every node’s priority ≥ its children’s.

random priority

Each node gets a random priority on insertion — this decides the shape.

rotation

A local restructuring that fixes the heap property while preserving BST order.

treap.js — keys ordered, priorities heaped
Ready
Each node shows its key (top) and random priority (bottom). The tree is a BST on keys and a max-heap on priorities. Inserting a key places it by BST order, then rotates it up while its priority beats its parent’s. Insert to build.
0
nodes
0
height
last rotations

How it works

The trick is that a treap’s shape is uniquely determined by its set of (key, priority) pairs, regardless of insertion order — the BST-on-keys and heap-on-priorities constraints together leave exactly one valid tree. So if the priorities are random, the tree you get is the same as if you had inserted the keys in a random order, which is known to produce an expected height of O(log n). Insertion is simple: place the new key as a normal BST leaf, then, while it has a higher priority than its parent, rotate it upward — each rotation preserves the BST order but lifts the high-priority node toward the root, restoring the heap property. Deletion is the mirror: rotate the node down until it’s a leaf, then snip it.

1

Give each node a random priority

On insertion, assign the new key a random priority. The tree must satisfy BST order on keys and max-heap order on priorities simultaneously.

2

Insert as a BST leaf

Descend by key comparisons and attach the new node as a leaf, exactly as in an ordinary BST. This keeps the BST property but may violate the heap property.

3

Rotate up to fix the heap

While the new node’s priority exceeds its parent’s, rotate it up. Each rotation is a local restructuring that preserves BST order while moving the higher priority toward the root.

Balanced in expectation

Because random priorities make the shape equivalent to random-order insertion, the expected height is O(log n). No AVL/red-black-style rules are needed — just rotations driven by priorities.

Height
O(log n) expected
Insert / delete
O(log n)
Rebalance
rotations only
Also called
randomized BST

The code

# treap insertion: BST on key, max-heap on random priority import random def insert(t, key): if t is None: return Node(key, priority=random.random()) if key < t.key: t.left = insert(t.left, key) if t.left.priority > t.priority: # heap violated t = rotate_right(t) # lift the child up else: t.right = insert(t.right, key) if t.right.priority > t.priority: t = rotate_left(t) return t # rotations preserve BST order, fix the heap

Quick check

1. What two structures is a treap at the same time?

2. Why does a treap stay balanced without complex rebalancing rules?

3. How is the heap property restored after inserting a key?

FAQ

What is a treap?

A randomized balanced BST that is at once a binary search tree on its keys and a max-heap on a random priority per node. Since its shape comes from the random priorities, not insertion order, it has O(log n) expected height and supports insert/delete/search in O(log n) expected time with only simple rotations.

How does a treap compare to AVL and red-black trees?

AVL and red-black trees guarantee worst-case O(log n) height via strict rules (more complex code). A treap only guarantees O(log n) in expectation, but it’s far simpler and supports split/merge easily — a popular choice when simplicity and those operations matter more than a worst-case bound.

What are split and merge on a treap?

Split divides a treap into two by a key (smaller keys in one, rest in the other); merge combines two treaps (all keys in one < all in the other) into one. Both are O(log n), and they make implicit-key treaps behave like arrays with fast range insert/erase/reverse.

What happens if two nodes get the same priority?

Priority ties can blur the unique shape and slightly hurt balance, but with wide-range random priorities (32–64 bits) collisions are negligible; implementations either rely on that or break ties deterministically. In practice it’s a non-issue.

Keep going

Finished this one? 0 / 98 Algorithms done

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More Algorithms