Overview

Bucket Sort is a distribution-based sorting algorithm that maps elements into ordered buckets, sorts each bucket locally, and concatenates buckets to produce a globally sorted array. When the mapping spreads items evenly (e.g., approximately uniform data or quantile-calibrated cut points) and the number of buckets matches the input scale, the algorithm achieves expected time.

Note

The comparison lower bound does not apply here because order arises from value-to-range mapping, not pairwise comparisons alone.


Intuition

Think of pouring pebbles through a sieve with evenly sized slots. Each slot (bucket) collects a narrow value range. Because each bucket receives few items, sorting inside a bucket is cheap; concatenating buckets in order yields the final sorted run.

  • Even spread ⇒ tiny buckets ⇒ linear behavior

  • Skewed spread ⇒ fat buckets ⇒ falls back to the bucket’s internal sorter


Pseudocode

function BUCKET_SORT(A, m):        // A[0..n-1] of numeric keys; m buckets
    B = array of m empty lists     // or contiguous ranges via two-pass layout
 
    // Distribute
    for j from 0 to length(A)-1:
        i = bucket_index(A[j], m)  // e.g., floor(m * A[j]) if A[j] ∈ [0,1)
        append A[j] to B[i]
 
    // Sort within buckets
    for i from 0 to m-1:
        STABLE_SORT(B[i])          // insertion sort for tiny buckets; mergesort/Timsort otherwise
 
    // Concatenate
    k = 0
    for i from 0 to m-1:
        for each x in B[i] (in order):
            A[k] = x
            k = k + 1

Tip

For cache efficiency, use a two-pass contiguous layout: (1) histogram counts, (2) prefix sums to compute offsets, (3) scatter into one output array partitioned by bucket, (4) sort each contiguous region in place.


Dry Run Example

Array A = [0.78, 0.17, 0.39, 0.26, 0.72, 0.94, 0.21, 0.12, 0.23, 0.68], with m = 5 buckets over using i = ⌊5x⌋:

BucketRangeElements (unsorted)After in-bucket sort
B[0][0.00, 0.20)0.17, 0.120.12, 0.17
B[1][0.20, 0.40)0.39, 0.26, 0.21, 0.230.21, 0.23, 0.26, 0.39
B[2][0.40, 0.60)
B[3][0.60, 0.80)0.72, 0.68, 0.780.68, 0.72, 0.78
B[4][0.80, 1.00)0.940.94

Concatenation in bucket order yields the globally sorted array.


Time Complexity

PhaseWork
Bucket allocation + concat
In-bucket sorting (expected) with insertion sort; with mergesort/Timsort
  • With uniform spread and : expected total is .

  • Worst case (heavy skew): one giant bucket ⇒ cost of the chosen in-bucket sort on items (e.g., for insertion, for mergesort/Timsort).

  • Space: (lists) or (two-pass arrays: counts + offsets).


Optimizations

  1. Choose wisely

    • Classic: to keep expected bucket size near 1.

    • Cache-aware: pick so typical bucket fits L1/L2.

    • Memory-bound: smaller + faster in-bucket sort.

  2. Quantile or CDF-based buckets Estimate the CDF via sampling; choose cut points at quantiles so buckets have similar expected occupancy, mitigating skew.

  3. Adaptive splitting Detect oversized buckets during the pass and split them (requires extra offsets but stabilizes performance).

  4. Hybrid interiors Use counting/radix inside buckets with small integer ranges; otherwise use insertion sort for tiny buckets and Timsort/mergesort for larger ones.

  5. Parallelization Per-thread histograms → reduce → prefix sums → parallel scatter → parallel per-bucket sorts.


Common Pitfalls

Warning

Rounding at the upper bound: Clamp i = min(m-1, floor(m*x)) to avoid i == m when x ≈ 1.0.

Warning

Skewed inputs: Heavy clustering collapses linear-time behavior. Prefer quantile buckets when distributions drift.

Warning

Unstable pipeline: Bucket sort is not inherently stable; stability depends on the in-bucket algorithm and concatenation order.

Warning

Too many small lists: With m ≈ n, per-bucket list overhead hurts. Prefer the two-pass contiguous layout to cut allocations and improve locality.


Use Cases

  • Numeric analytics / telemetry where normalization to approximates uniformity.

  • Range partitioning stages in databases and analytics (map → reduce → sort).

  • Pre-sorting for merges: form small sorted runs cheaply before a merge-heavy phase.

  • Hybrid pipelines with Radix Sort and Counting Sort.


AlgorithmModelExpected TimeWorst TimeStableNotes
Bucket SortDistribution or (by in-bucket choice)DependsGreat when spread is even
Counting SortNon-comparisonFor bounded integer range
Radix SortNon-comparisonDigitwise; pairs well with bucketing
Quick SortComparisonStrong cache locality in practice

Summary

  • Map elements into ordered buckets, sort each bucket, and concatenate to finish.

  • With balanced buckets and , runtime is expected .

  • Robust performance requires quantile-aware bucket boundaries, cache-friendly layout, and a sensible in-bucket sorter.


See also