Skip to main content
← All posts

Spreadsort: Mechanism, Complexity Analysis & Interactive Visualizer

Md. Harun-Or-RoshidNov 5, 20269 min readArticle
Spreadsort: Mechanism, Complexity Analysis & Interactive Visualizer
Hybrid Sorting · Article 30 of 62

Spreadsort

A state-of-the-art hybrid distribution sort: combines bucket partitioning based on key bits with standard comparison algorithms for small bins, outperforming Quicksort on many datasets.

How it works

Spreadsort, designed by Steven J. Ross in 2002, is a high-speed hybrid algorithm included in the Boost C++ libraries. It integrates radix/bucket distribution sorting with comparison sorting:

  1. Range & Bin Size Calculation: Scan the array to find the minimum and maximum keys. Compute a distribution threshold and select a bin count \(K\) based on the array size and key ranges.
  2. Distribution Phase: Partition the input array into \(K\) buckets using the most significant bits or proportional divisions of the elements' key values.
  3. Adaptive Recursion:
    • If a bucket contains elements with a large range of values, recursively apply Spreadsort to that bucket.
    • If a bucket size is small or the range of values is tight, switch to a fast comparison-based sort (like Insertion Sort or standard Quicksort).

Complexity

Best time
O(n)
Average time
O(n log n)
Worst time
O(n log n)
Extra space
O(k)
Stable
No
In-place
No
Spreadsort runs in \(O(n)\) best-case time when data is uniformly distributed, and degrades gracefully to \(O(n \log n)\) under highly skewed or worst-case distributions.

Interactive visualization

Pseudocode

procedure spreadsort(A):
  n ← length(A)
  if n < threshold:
    comparisonSort(A)
    return
    
  minVal, maxVal ← findMinMax(A)
  if minVal == maxVal:
    return
    
  K ← calculateBucketCount(n)
  buckets ← array of K empty lists
  
  for each x in A:
    idx ← getBucketIndex(x, minVal, maxVal, K)
    buckets[idx].append(x)
    
  A ← empty
  for each bucket in buckets:
    spreadsort(bucket)  # Recurse or fallback to insert sort
    A.appendAll(bucket)

JavaScript implementation

function spreadsort(arr) {
  const n = arr.length;
  if (n < 16) {
    // fallback to insertion sort for small partitions
    for (let i = 1; i < n; i++) {
      let key = arr[i];
      let j = i - 1;
      while (j >= 0 && arr[j] > key) {
        arr[j + 1] = arr[j];
        j--;
      }
      arr[j + 1] = key;
    }
    return arr;
  }
  
  let min = arr[0], max = arr[0];
  for (let x of arr) {
    if (x < min) min = x;
    if (x > max) max = x;
  }
  if (min === max) return arr;
  
  const K = Math.floor(n / 4) || 2;
  const buckets = Array.from({ length: K }, () => []);
  const range = max - min;
  
  for (let x of arr) {
    const idx = Math.min(K - 1, Math.floor(((x - min) / range) * K));
    buckets[idx].push(x);
  }
  
  let current = 0;
  for (let b = 0; b < K; b++) {
    spreadsort(buckets[b]);
    for (let x of buckets[b]) {
      arr[current++] = x;
    }
  }
  return arr;
}

Pros and cons

Pros

  • Significantly faster than O(n log n) comparison sorts for integer and float keys.
  • Adaptive: drops to insertion sort when bins get small.
  • Excellent cache locality during bucket divisions.

Cons

  • Requires O(n) temporary space to hold bucket buffers.
  • Key-dependent: only works with keys that can be numerically partitioned.
  • Unstable sorting order.

When (not) to use it

  • Large datasets of numeric/string keys: Highly recommended when sorting huge integer, float, or structured keys with uniform properties.
  • Generic object sorting: Avoid when sorting objects based on complex comparisons that cannot be mapped easily to distribution divisions.
Up next: Comb Sort — a fast improvement on Bubble Sort that uses a decreasing gap size to eliminate small values at the end of the array ("turtles").
Share:
Share on X
Share on LinkedIn
Share on Facebook
Share on Reddit
Share on WhatsApp
Share on Telegram
Copy link

Related reading

Spreadsort Sorting Algorithm & Guide | Draftsbook · Draftsbook