Splay Tree Sort: Mechanism, Complexity Analysis & Interactive Visualizer
Splay Tree Sort
A self-adjusting search tree sort: elements are inserted into a Splay Tree, splaying recently accessed nodes to the root, followed by an in-order retrieval.
How it works
Splay Tree Sort is a variations of BST sort using a Splay Tree, a self-balancing binary search tree. Every insertion triggers a sequence of tree rotations called "splaying" that moves the newly inserted node to the root:
- Splay Tree Insertion: For each element in the input, insert it into the BST. If a key is found or inserted, we "splay" it to the root using Zig-Zig, Zig-Zag, Zag-Zig, or Zag-Zag double-rotations.
- Amortized Balancing: Splaying doesn't guarantee strict height balance (like AVL or Red-Black trees), but it achieves a logarithmic amortized cost per operation. Frequently accessed or recently inserted elements stay near the root.
- In-Order Traversal: Once all elements are splayed and stored, an in-order traversal collects the items in sorted order and copies them back.
Complexity
Interactive visualization
Pseudocode
procedure splayTreeSort(A): root ← null for each x in A: root ← insert(root, x) i ← 0 inOrderTraversal(root, A, i) procedure insert(root, x): if root is null: return new Node(x) root ← splay(root, x) newNode ← new Node(x) if x < root.value: newNode.right ← root newNode.left ← root.left root.left ← null else: newNode.left ← root newNode.right ← root.right root.right ← null return newNode
JavaScript implementation
class SplayNode { constructor(val) { this.val = val; this.left = null; this.right = null; } } function rotateRight(x) { const y = x.left; x.left = y.right; y.right = x; return y; } function rotateLeft(x) { const y = x.right; x.right = y.left; y.left = x; return y; } function splay(root, val) { if (!root || root.val === val) return root; if (val < root.val) { if (!root.left) return root; if (val < root.left.val) { root.left.left = splay(root.left.left, val); root = rotateRight(root); } else if (val > root.left.val) { root.left.right = splay(root.left.right, val); if (root.left.right) root.left = rotateLeft(root.left); } return !root.left ? root : rotateRight(root); } else { if (!root.right) return root; if (val < root.right.val) { root.right.left = splay(root.right.left, val); if (root.right.left) root.right = rotateRight(root.right); } else if (val > root.right.val) { root.right.right = splay(root.right.right, val); root = rotateLeft(root); } return !root.right ? root : rotateLeft(root); } } function splayTreeSort(arr) { let root = null; for (let val of arr) { if (!root) { root = new SplayNode(val); } else { root = splay(root, val); const newNode = new SplayNode(val); if (val < root.val) { newNode.right = root; newNode.left = root.left; root.left = null; } else { newNode.left = root; newNode.right = root.right; root.right = null; } root = newNode; } } let i = 0; function inOrder(node) { if (!node) return; inOrder(node.left); arr[i++] = node.val; inOrder(node.right); } inOrder(root); return arr; }
Pros and cons
Pros
- Amortized cost per operation is O(log n), matching best comparison sorts.
- Highly adaptive: performs exceptionally well on cache/locality accesses.
- Does not require balance metadata (like AVL heights or Red-Black colors).
Cons
- High constant factors due to extensive rotation steps during insertion.
- Requires O(n) extra space for the tree structure.
- Unstable: tree adjustments can change the order of equal keys.
- Destructive read-access path: searches mutate the tree structure.
When (not) to use it
- Working with biased data accesses: Excellent when some elements are queried or modified repeatedly.
- Standard in-memory arrays: Timsort or Quicksort are significantly faster due to the overhead of pointer updates and splaying cycles.
Related reading
Sleep Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A unique concurrency-based sorting algorithm: spawns a separate thread for each element, sleeping for a duration proportional to the element value before writing it to the output.
By Md. Harun-Or-Roshid
Cube Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A parallel dimension sorting algorithm: organizes elements in a 3D coordinate cube and sorts vectors along the height, width, and depth axes sequentially to achieve sorted order.
By Md. Harun-Or-Roshid
Patience Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A card-game inspired sorting algorithm: distributes elements onto a series of piles such that each pile's top is \(\ge\) the incoming value, then performs a multi-way merge across pile tops.
By Md. Harun-Or-Roshid
Library Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A gapped variation of Insertion Sort: leaves empty slots (gaps) in the array, allowing elements to be inserted in \(O(1)\) shift time on average by avoiding massive shifts.
By Md. Harun-Or-Roshid