The words "on average" are not a number
“Quicksort is on average” is a statement about a distribution. It is delivered as though it were a statement about a number.
The distribution exists, it is not hard to measure, and it contains everything the average discards: the spread, the shape, the tail, and — the part that usually decides whether an algorithm is usable — how bad the bad case is and how often it happens.
What the distribution looks like
Six hundred independent random inputs at , randomised pivot:
| statistic | comparisons |
|---|---|
| best of 600 | 4,282 |
| median | 4,908 |
| mean | 4,945 |
| 99th percentile | 6,030 |
| worst of 600 | 6,543 |
The mean sits 0.8% above the median, which is the signature of a right skew, and the worst run is 32% above the mean. The relative standard deviation is 6.8%.
For a randomised algorithm that is a very well-behaved distribution, and the reason is worth understanding: quicksort’s total cost is a sum of many partition costs, most of which are close to balanced, so the central limit theorem applies and the total concentrates tightly around its mean. A single unlucky pivot near the top of the recursion hurts, but it is one term among many.
The distribution is nonetheless skewed. There is a floor — nothing can average below , which at is 3,875, and even the luckiest of these six hundred runs came in at 4,282 — and no ceiling short of . So the distribution has a hard left edge and a long thin right tail, which is the shape almost every cost distribution in this subject has.
Why the tail is the interesting part
For a batch job that sorts a million arrays and reports total time, the mean is exactly the right statistic: total cost is the sum, and the sum of a million draws is the mean times a million with negligible variance.
For almost anything interactive, it is the wrong statistic, and the reason is arithmetic rather than philosophical.
A web request that performs a hundred independent sorts sees the maximum of a hundred draws from this distribution, not the mean. If each sort’s 99th percentile is 22% above its mean, then a request touching a hundred of them will almost certainly contain at least one sort at that level, and quite possibly several. Tail latency compounds with fan-out, and the more components a request touches, the more the tail of each one governs the whole.
This is why serious systems work quotes p99 and p999 rather than means, and why “average case ” is not a specification anyone can build a latency budget from. The distribution is what a budget needs, and the classification never carries one.
The tail does not grow, and that had to be checked
The measurement above answers a question the classification cannot: does the tail get relatively worse as grows?
It is easy to imagine that it would. More elements means more pivots means more chances for a bad one. But it also means more terms in the sum, and more terms means tighter concentration. Which effect wins is not obvious from the algorithm and is immediate from the data: the worst-to-mean ratio runs from 1.38 at n = 64 down to 1.18 at n = 2,048, so if anything the tail tightens slightly as n grows. Concentration wins.
That is a real result and it is the kind of thing an average-case bound is silent about. An algorithm whose mean was and whose 99th percentile grew like would satisfy every textbook statement about quicksort and be unusable in a latency-sensitive system.
The site’s figure asserts the absence of a trend — if the ratio between the largest and smallest worst-to-mean ratios ever exceeded 2, the figure would fail to build. That is the must-be-able-to-fail discipline applied to a claim about a distribution rather than about a class.
How many samples is enough
An average computed from a sample is an estimate with an error, and quoting one without knowing the error is the same category of mistake as quoting a class without naming the input.
The question is answerable directly by watching the running mean settle.
The convergence is fast because the distribution is tight. For a heavier-tailed quantity — the number of probes in a nearly-full hash table, say — the same picture would still be wandering after five hundred samples, and the honest response would be to take more or to report a percentile instead of a mean.
Showing the convergence is cheap, and it converts a bare claim of 600 trials into a demonstration that 600 was enough.
The distribution that is not tight
Randomised quicksort’s distribution is well behaved, and picking it as the example risks suggesting that distributions are usually a formality. They are not, and the contrast is available on this site.
The clean counter-example is a deterministic pivot rule measured across inputs rather than across coin flips. Quicksort taking the first element has a comparison count of 4,887 on random input at and 130,816 on a sorted one — a factor of 27, and the sorted case is not somewhere in the right tail of the random-input distribution. It is off the chart entirely, three orders of magnitude past the worst random run.
That is what a genuinely heavy-tailed cost looks like, and no amount of sampling from random inputs would ever discover it, because sorted arrays have probability essentially zero under a uniform distribution over permutations. Sampling from the assumed distribution cannot find inputs the assumed distribution does not generate, and real data is not drawn from a uniform distribution over permutations.
This is the practical difference between average-case and expected-case, and it is worth its own essay. A distribution measured over random inputs describes what happens when the data is random. It says nothing about what happens when it is not, and the ways in which real data fails to be random — sortedness, near-sortedness, few distinct values, adversarial construction — are exactly the ways that break these algorithms.
Three things called “average”
The word covers three quite different guarantees, and conflating them is the most common error in this area.
Average case. Averaged over an assumed distribution of inputs. Quicksort with a first-element pivot is in the average case, meaning: given a uniformly random permutation. If the input is sorted — which is an extremely common thing for real data to be — the guarantee does not apply and the algorithm is quadratic. This is the weakest of the three, because it depends on an assumption about the data that may not be checkable and that an adversary can violate deliberately.
Expected. Averaged over the algorithm’s own randomness. Quicksort with a random pivot is expected on every input, because the randomness is in the coin flips rather than in the data. No input can force the bad case; only bad luck can. This is much stronger, and what randomisation buys is precisely the upgrade from the first guarantee to this one.
Amortised. Averaged over a sequence of operations, with no randomness at all. A dynamic array’s append is amortised: a worst-case guarantee about the total cost of any sequence. Stronger again, because no distribution is assumed and no luck is involved.
All three get written as “on average” in casual usage. The three underlying guarantees are: if the data is nice, barring bad luck, and always, over the sequence. Those are not close to the same statement.
What a distribution figure should show
Having argued that distributions matter, it is worth being concrete about what to draw, because a histogram is not automatically informative.
The floor, if there is one. Quicksort’s distribution has a hard left edge at and knowing that changes how the left tail reads: the mass piled near the bottom is against a wall rather than trailing off.
A high percentile, marked. The 99th is more actionable than the maximum, because the maximum of a sample is itself a highly variable statistic — take another 600 runs and it moves — while the 99th percentile is stable.
The mean, marked, but not alone. Drawing the mean without the spread is what the classification already does.
The sample size and the seeding. A distribution from 600 runs with stated seeds is reproducible; one from Math.random() is a different distribution on every build and its caption cannot be trusted.
Why the shape is always the same
Almost every cost distribution in this subject has the same shape — a hard floor, a peak near it, and a long thin right tail — and the reason is structural rather than coincidental.
The floor is real. Sorting has an information-theoretic minimum that no input can get under. A hash table insertion takes at least one probe. A dynamic array append costs at least one write. Costs are bounded below by the work that must be done and unbounded above by however badly things can go.
The peak is concentration. Most of these algorithms are sums of many small random contributions — quicksort’s partition costs, a hash table’s probe counts, a random tree’s path lengths — and sums of many independent contributions concentrate. That is the central limit theorem doing what it does.
The tail is the rare compound failure. Getting an unusually bad total requires several of the contributions to be bad at once, which is rare, and the rarity falls off faster than the badness grows. Hence thin.
The practical upshot is that the mean and the median are close for almost everything here, and neither of them is the 99th percentile. Reporting the mean and reporting the median are nearly the same act; reporting either and calling it the cost is the omission.
The general form of the complaint
A single number summarising a distribution throws away information, and which information it throws away depends on which number is picked. That is unavoidable and it is not the problem.
The problem is that the convention in this subject is to report one summary — the average — and to report it in a notation that cannot express the others. There is no standard way to write “the 99th percentile is with constant 1.13”, and so the fact goes unstated, and systems get built on a mean.
Everything on this site that reports an average also reports the distribution it came from, because the distribution is cheap to measure and it is where the surprises are.