$ \def\compare{ {\mathrm{compare}} } \def\swap{ {\mathrm{swap}} } \def\sort{ {\mathrm{sort}} } \def\insert{ {\mathrm{insert}} } \def\true{ {\mathrm{true}} } \def\false{ {\mathrm{false}} } \def\BubbleSort{ {\mathrm{BubbleSort}} } \def\SelectionSort{ {\mathrm{SelectionSort}} } \def\Merge{ {\mathrm{Merge}} } \def\MergeSort{ {\mathrm{MergeSort}} } \def\QuickSort{ {\mathrm{QuickSort}} } \def\Split{ {\mathrm{Split}} } $
We asked:
Can we sort $n$ elements faster than $O(n \log n)$?
I claimed: not really?
Follow execution of $A$ on all inputs from $S_n$
Define a binary tree:
Form this tree for all comparisons made on all inputs in $S_n$
for i = 2 to n do
| j <- i
| while j > 1 and compare(a, j-1, j) do
| | swap(a, j, j-1)
Claim. If $A$ does not distinguish permutations $a$ and $b$ with $a \neq b$, then $A$ does not sort both $a$ and $b$.
Why?
Consequence. If $A$ sorts all arrays of size $n$, then every leaf of $A$’s decision tree is labeled with a single permutation array.
Why?
How many leaves must a correct decision tree have?
How deep must decion tree be?
Claim. $\log n! = \Omega(n \log n)$
Theorem. Any algorithm that sorts all permutations of size $n$ using only $\compare$ and $\swap$ operations requires $\Omega(n \log n)$ comparisons.
The $\Omega(n \log n)$ lower bound critically assumes that array is only accessed and modified with $\compare$ and $\swap$.
What if we have more refined access?
What if we see binary representation of elements?
Observation. If $a$ consists of only $0$s and $1$s, we can sort $a$ in $O(n)$ time.
How?
Assume $a$ consists of $n$ numbers, each with binary representation of $B$ bits
Inspired by QuickSort:
How to perform first split?
Input:
Behavior:
BitSplit(a, i, j, b):
left <- i, right <- j
while left < right do:
if a[left][b] = 1 and a[right][b] = 0 then
swap(a, left, right)
left++, right--
else
if a[left][b] = 0 then left++
if a[right][b] = 1 then right--
endif
endwhile
if a[right][b] = 0 then return right+1 else return right
RadixSort(a, B): # B is number of bits
RadixSort(a, 1, size(a)+1, B)
RadixSort(a, i, j, b):
if j - i <= 1 then
return
endif
m <- BitSplit(a, i, j, b)
RadixSort(a, i, m, b-1)
RadixSort(a, m, j, b-1)
Arithmetic!