Counting sort and radix sort
Why comparison sorts cannot beat O(n log n), and how counting sort and radix sort beat it anyway for small integer keys.
Counting sort
static int[] CountingSort(int[] a){ if (a.Length == 0) return a; int min = a.Min(), max = a.Max(); var count = new int[max - min + 1]; // k = range of values foreach (int v in a) count[v - min]++; // 1. count for (int i = 1; i < count.Length; i++) // 2. running totals = end positions count[i] += count[i - 1]; var output = new int[a.Length]; for (int i = a.Length - 1; i >= 0; i--) // 3. place, right to left = stable output[--count[a[i] - min]] = a[i]; return output;} Console.WriteLine(string.Join(" ", CountingSort([4, 1, 3, 4, 0, 2, 1, 4, 3, 1])));Console.WriteLine(string.Join(" ", CountingSort([3, -2, 0, 3, 1])));0 1 1 1 2 3 3 4 4 4 -2 0 1 3 3
Radix sort
// LSD radix sort for non-negative integers, base 10static void RadixSort(int[] a){ if (a.Length == 0) return; int max = a.Max(); var output = new int[a.Length]; for (int exp = 1; max / exp > 0; exp *= 10) // 1, 10, 100, ... { var count = new int[10]; foreach (int v in a) count[v / exp % 10]++; for (int d = 1; d < 10; d++) count[d] += count[d - 1]; for (int i = a.Length - 1; i >= 0; i--) // stable output[--count[a[i] / exp % 10]] = a[i]; Array.Copy(output, a, a.Length); }} int[] data = { 170, 45, 75, 90, 802, 24, 2, 66 };RadixSort(data);Console.WriteLine(string.Join(" ", data));2 24 45 66 75 90 170 802
| Algorithm | Time | Works for | Stable |
|---|---|---|---|
O(n log n) | |||
O(n + k) | |||
O(d × (n + b)) | |||
O(n) on average |
"algorithms" → "aghilmorst". Use an array of 26 counters.
Show a hint
count[c - 'a']++ for each character, then append each letter count[i] times. StringBuilder.Append(char, repeatCount) helps (add using System.Text;).
Show the solution
using System.Text; static string SortLetters(string s){ var count = new int[26]; foreach (char c in s) count[c - 'a']++; var sb = new StringBuilder(s.Length); for (int i = 0; i < 26; i++) sb.Append((char)('a' + i), count[i]); return sb.ToString();} Console.WriteLine(SortLetters("algorithms"));aghilmorst
Remember
Comparison sorts cannot beat about n log n comparisons in the worst case. Counting sort counts each value and places items directly: O(n + k) for keys in a range of k. Radix sort applies a stable counting sort digit by digit: O(d × (n + b)). These sorts only work for integer-like keys; for general objects use a comparison sort.