What a bound is

The constant the notation drops

Six algorithms on this site are Θ(n log n) and their comparison counts differ by a factor of two. The class is what they have in common; the constant is what distinguishes them. It is measurable to three digits, it is the number that actually decides between them, and it is precisely the number the classification is designed to discard.

Once two algorithms have both been placed in Θ(nlogn)\Theta(n \log n), the classification has said everything it is going to say. It has also implied that a further question exists, because two algorithms in the same class are not the same algorithm, and the difference between them is a number.

That number is the constant. If an algorithm’s comparison count is asymptotically cnlog2nc \cdot n \log_2 n, then cc is what the notation discards, and cc is what decides which of two same-class algorithms does less work.

It is not hard to measure. Divide the measured count by nlog2nn \log_2 n at every size and look at what it settles to.

Same class, different constantsEvery algorithm here fits n log n on random input. The bar is the fitted constant — comparisons divided by n log n — and the largest is 1.9 times the smallest. That factor is invisible in the notation and is the whole of what distinguishes these algorithms by this measure.comparisons ÷ n log nMerge sort0.855Merge sort with a cutoff0.992Quicksort, random pivot1.018Quicksort, first-element1.082Quicksort, median of three1.117Shellsort1.246Heapsort1.649all of these fit n log n1.9× between best and worst
Fig. 1 Every algorithm that the site’s fitting machinery placed in the linearithmic class, with its measured constant. Merge sort settles at 0.838 comparisons per n log₂ n; heapsort at 1.613. Both are Θ(n log n). One does 1.9 times the comparing.

Where the number comes from

The fit that grants a class computes this on the way. For a candidate class ff, the ratio count(n)/f(n)\text{count}(n) / f(n) is computed at every measured size, and the class is granted only if that ratio stays flat. If it stays flat, the value it stays flat at is the constant.

So the constant is not an extra measurement bolted on. It is a by-product of the test, and the same evidence that establishes the class establishes the number.

Measured on random input from n = 32 to n = 4,096:

algorithm constant spread
merge sort 0.838 1.21
quicksort, random pivot 0.995 1.40
quicksort, first element 1.051 1.29
merge sort with cutoff 1.059 1.14
quicksort, median of three 1.120 1.09
Shellsort 1.206 1.41
heapsort 1.613 1.26

The spread column is how flat the ratio was — 1.00 would be perfectly flat, and everything here is within 1.41. That flatness is what entitles the middle column to be called a constant rather than a number that happens to be true at one size.

Reading the table

Several things in it are more informative than the classification.

Merge sort is the comparison champion, and it is not close. At 0.838 it does 48% fewer comparisons than heapsort and 25% fewer than randomised quicksort. Where comparisons are what cost — sorting strings, sorting by a user-supplied comparator, sorting anything where the comparison is a function call — merge sort is the algorithm and the margin is large.

Heapsort is the most expensive thing in the class. This surprises people who know heapsort as the algorithm with the good worst case. Both facts are true: heapsort’s worst case is Θ(nlogn)\Theta(n \log n) with no bad inputs at all, which is a genuinely valuable guarantee, and it pays for that guarantee with a constant nearly twice merge sort’s. The sift-down operation compares a node against both children at every level, and that “both” is most of the factor.

Adding an insertion-sort cutoff makes merge sort worse at comparing. 0.838 goes to 1.059, a 26% increase. Insertion sort is comparison-hungry on the small subarrays it takes over, and the hybrid pays for it. Every production sort implements a cutoff anyway, for reasons that are about memory traffic rather than comparisons — which is exactly the kind of thing a single-count analysis cannot see.

The three quicksorts cluster tightly. 0.995, 1.051, 1.120 — all within 13% of each other on random input. The pivot rule barely matters here, which is worth knowing, because the pivot rule matters enormously on inputs that are not random. First-element pivoting costs 130,816 comparisons on a sorted array of 512 where random pivoting costs 5,490, a factor of 24. The constants on random input say nothing about that, and the distribution does.

What a constant is not

It is not a running time, and the ranking by constants is not the ranking by speed. Merge sort’s comparison constant is the best in the table and merge sort allocates a buffer the size of the input, which quicksort does not. On real hardware, quicksort’s locality frequently beats merge sort’s comparison economy. Nothing in this table can establish that, and the second count exists because of it.

It is not transferable between cost models. These are comparison constants. The write constants would rank the same algorithms differently — selection sort, which is not even in this table because it is quadratic, does fewer writes than anything here. Every constant is a constant for a named count, and quoting one without naming the count is the same error as quoting a class without naming the input.

It is not stable across input distributions. Merge sort’s constant is 0.838 on random input. On already sorted input its comparison count drops to 2,304 at n = 512, against 3,964 on random, and the fitted constant is exactly 0.500 — one comparison per element per level rather than two, because merging two already-ordered runs exhausts one side and copies the rest without asking. Same algorithm, same class, different number. The table above is a table about random input and says so.

It is not a fundamental property of the algorithm. It is a property of this implementation of the algorithm, under this cost model. A merge sort that compares a[j] < a[i] and one that compares a[i] <= a[j] do the same number of comparisons but differ in stability; a merge sort that checks whether the two halves are already in order does dramatically fewer comparisons on nearly-sorted input and slightly more on random. The constant moves.

Comparison counts against n, random inputMeasured counts on logarithmic axes, where a power law is a straight line and its exponent is the slope. The quadratic algorithms rise at twice the gradient of the linearithmic ones, and the vertical gaps between the parallel lines are the constants the notation discards.10010³10010³10⁴10⁵ncomparisonsMergeHeapsortQuicksortShellsorta power law is a straight line herecomparisons, counted exactly
Fig. 2 The four algorithms whose constants the table reports, drawn. The lines are parallel, which is the classification: they are all in the same class. The vertical distances between them are the constants, and they persist all the way across — that persistence is exactly what makes the constant a constant.

The constant is not one number either

An honest constant needs three qualifiers, and dropping any of them turns it back into folklore.

Which count. The table above is comparison constants. Do the same exercise on writes and merge sort’s number is exactly 1.000 writes per nlog2nn \log_2 n — one write per element per level, with a spread of 1.00, which is as clean a constant as this site measures — while heapsort’s is 1.792. The ratio between them is close to the comparison ratio, coincidentally, and there was no reason it had to be. Do it on total reads and writes and the ordering shifts again, because merge sort’s buffer copy costs traffic that quicksort never pays. Every count is a different question and every question has its own constant.

Which input. Merge sort’s comparison constant is 0.838 on random input and about 0.49 on sorted input, because merging two already-ordered runs exhausts one side early and skips the rest. Same algorithm, same class, a factor of 1.7 between the two numbers. Any constant quoted without its input distribution is quoting one column of a table and hiding the rest.

Which implementation. The constant is a property of the code, not of the idea. A merge that checks whether the last element of the left run is below the first of the right — a two-line addition that costs one comparison per merge — takes merge sort’s constant on already-sorted input from 0.500 to near zero, and leaves it untouched on random input. The algorithm is still merge sort. The number moved.

This is why the constants on this site are always presented with a range, an input and a link to the source rather than as facts about sorting algorithms in general.

The constant against the floor

There is one comparison in which the constant becomes more than a relative measure, and it is the most useful thing on this page.

No comparison sort can average fewer than log2(n!)\log_2(n!) comparisons, and log2(n!)nlog2n1.44n\log_2(n!) \approx n \log_2 n - 1.44n. So the ideal constant, asymptotically, is 1 — and any algorithm’s measured constant can be read as a distance from optimality rather than as a distance from its competitors.

At n = 256 the floor is 1,684 comparisons. Averaged over sixteen random inputs:

algorithm comparisons multiple of the floor
merge sort 1,722 1.02
quicksort, first element 2,069 1.23
quicksort, random pivot 2,086 1.24
merge sort with cutoff 2,170 1.29
quicksort, median of three 2,228 1.32
Shellsort 2,447 1.45
heapsort 3,300 1.96
insertion sort 16,317 9.69
bubble sort 32,436 19.26
selection sort 32,640 19.38

Merge sort is within 2.2% of a bound that no algorithm can beat. That is an extraordinary thing to be able to say about a practical algorithm, and it is not visible from the classification, which merely puts merge sort in the same box as heapsort at 96% above the floor.

This is the floors field’s subject and it is the natural home of the constant. Comparing an algorithm to its competitors identifies which is better among the ones somebody thought of. Comparing it to the floor establishes how much room is left.

Comparisons used, as a multiple of the floor, n = 256The information-theoretic floor at n = 256 is 1,684 comparisons: a binary decision tree with 256! leaves cannot be shallower than that. The bar is what each algorithm averaged over 16 random inputs, divided by the floor. Merge sort comes within 2% of it; Selection sort uses 19 times as many.the floorMerge sort1.02×Quicksort, first1.23×Quicksort, random1.24×Merge sort + cutoff1.29×Quicksort, median-31.32×Shellsort1.45×Heapsort1.96×Insertion sort9.69×Bubble sort19.26×Selection sort19.38×floor = log₂(256!) = 1,684 comparisonsmean of 16 runs, against a proved bound
Fig. 3 The same numbers as a picture. The green line is the information-theoretic floor and nothing crosses it. Merge sort nearly touches it. The three quadratic algorithms are off the scale of usefulness — nineteen times the floor — which is a far more informative statement than “quadratic”.

What the constants say about the algorithms

Read as a group rather than as a ranking, the numbers say something about how each algorithm spends its comparisons.

Merge sort spends almost none of them wastefully. Its comparison count is close to the theoretical minimum because merging two sorted runs extracts nearly a full bit of information per comparison: each one determines the next element of the output and nothing is repeated. The decision-tree bound says a perfect algorithm extracts exactly one bit per comparison, and merge sort’s 2.2% gap at n = 256 is how close a practical algorithm gets.

Heapsort spends about half of them establishing things it will discard. Sifting an element down compares it against both children to decide which way to go, and the losing comparison contributes nothing to the final order — it only decides which subtree to descend. That structural waste is the factor of two.

Quicksort spends them on partitions that are not quite balanced. A perfectly balanced partition would give nlog2nn \log_2 n comparisons and a constant near 1. Random pivots give expected partitions at the 25/75 mark on average rather than 50/50, so the recursion is slightly deeper than optimal, and the measured 0.995 is what that costs. Median-of-three improves the balance and adds comparisons to compute the median, and the measured 1.120 says the second effect wins at these sizes — which is a genuinely surprising result and would not be visible without the number.

Shellsort’s 1.206 is not really a constant at all. Shellsort’s complexity depends on its gap sequence in a way that is still not fully settled theoretically, and the class the fit grants it — nlognn \log n, spread 1.41 — is the loosest fit on the site. That looseness is information: it is the fit saying that this algorithm is less well described by a single class than the others, which matches what is known about it.

Comparison counts against n, already sorted inputMeasured counts on logarithmic axes, where a power law is a straight line and its exponent is the slope. The quadratic algorithms rise at twice the gradient of the linearithmic ones, and the vertical gaps between the parallel lines are the constants the notation discards.10010³10010³10⁴10⁵ncomparisonsMergeMergeQuicksortHeapsorta power law is a straight line herecomparisons, counted exactly
Fig. 4 The same four algorithms on already sorted input rather than random. Merge sort’s line drops relative to the others — merging pre-ordered runs is cheap — while heapsort’s barely moves, because heapsort does the same work regardless of what it is given. Constants are per-input, and this is what that looks like.

Why the constants are so rarely quoted

The obvious question, given how easy the measurement is: why does nobody publish these?

Partly because they are implementation-specific and therefore feel unrigorous. A constant that changes when the inner loop is rewritten is not a theorem, and the culture around algorithm analysis is oriented towards theorems.

Partly because they are published, in the specialist literature, and mostly for the specific case of comparison counts under specific input models — Knuth computes many of them exactly, and the exact asymptotic constant for merge sort’s average comparison count is known. What is rare is not the number but the habit of putting it next to the class as a matter of course.

And partly because a constant invites the question of what it is a constant of, and answering that question honestly means naming the cost model, the input distribution and the implementation. That is three more sentences than “it’s O(nlogn)O(n \log n)”, and the three sentences are where the actual information is.

Comparisons and swaps at n = 512Selection sort performs the most comparisons of any algorithm here and among the fewest swaps — it never moves an element it does not have to. Ordering these algorithms by comparisons and ordering them by swaps gives two different orders, which is why the question "how many operations" needs the operation named before it has an answer.comparisonsswapsInsertion sort63,071 / 0Selection sort130,816 / 504Bubble sort129,688 / 62,563Merge sort3,964 / 0Heapsort7,653 / 4,170Quicksort5,049 / 2,380n = 512, random inputcounted in the same run
Fig. 5 The reason the third sentence matters. Comparisons and swaps for the same algorithms and the same runs — two constants, two rankings. A constant is always a constant for a named quantity, and changing the quantity changes the answer.

What to do with a constant

Three uses, in increasing order of how much they justify the measurement.

Choosing between same-class algorithms. Where comparisons dominate, merge sort’s 0.838 against heapsort’s 1.613 is decisive, and no amount of thinking about classes would have got there.

Comparison counts against n, random inputMeasured counts on logarithmic axes, where a power law is a straight line and its exponent is the slope. The quadratic algorithms rise at twice the gradient of the linearithmic ones, and the vertical gaps between the parallel lines are the constants the notation discards.10010³10010³10⁴10⁵ncomparisonsMergeMergeQuicksortShellsorta power law is a straight line herecomparisons, counted exactly
Fig. 6 Four algorithms whose constants differ by 44%, drawn on the axes where a constant is a vertical offset. The lines are parallel — same class — and the gaps between them persist across the whole range, which is what makes the offsets constants rather than coincidences at one size.

Estimating. A constant makes the class into an arithmetic prediction. Merge sort on a million elements: 0.838×106×201.7×1070.838 \times 10^6 \times 20 \approx 1.7 \times 10^7 comparisons. That is a number to multiply by a cost per comparison and set against a budget. The class alone offers nothing to multiply.

Detecting that something is wrong. This is the one that pays for itself. If an implementation’s constant is 2.5 where the reference implementation measures 0.84, the class still fits, the curve is still straight, and something is doing three times the work it should. A fitted exponent will not catch that, because a constant factor does not change a slope. The constant is the only thing that will.