0123456789
ALGORITHMS.ANIMATED · O(N) SORTING

Linear Sorting Explained with Animations

Sorting in O(n) time — faster than the comparison barrier. Learn counting sort, radix sort, and bucket sort through stunning animations. No comparisons needed!

// WHAT YOU'LL LEARN

🔢Counting Sort
📇Radix Sort (LSD)
🪣Bucket Sort
Interactive Sorter
O(n) Complexity
📋Properties & Facts
Beginner·20 min·Algorithms · Sorting
Reviewed by Reviewed by CodeTikki Editorial Team

// DEFINITION

What is
linear sorting?

Linear sorting refers to sorting algorithms that run in O(n) time — faster than the O(n log n) barrier that limits all comparison-based sorts. They achieve this by not comparing elements at all — instead, they exploit the structure of the data (value range, digits, distribution).

The trade-off: they only work on specific data types. Counting sort needs a small value range. Radix sort needs fixed-width integers. Bucket sort needs uniform distribution. But when the conditions are met, they are dramatically faster than quicksort or merge sort.

COMPARISON SORT — O(n log n)
5
2
8
1
9
3
5 > 2? ✓ swap
5 < 8? ✓ keep
8 > 1? ✓ swap
... compare every pair ...
~n × log₂(n) comparisons
COUNTING SORT — O(n + k)
0
1
2
3
5
8
9
Count: 0→1, 1→1, 2→1, 3→1, 5→1, 8→1, 9→1
Write out in order: 0,1,2,3,5,8,9
No comparisons at all! ✓
n + k operations only

// METHOD 1 · O(n + k)

Counting
Sort.

The simplest linear sort. Count how many times each value appears, compute prefix sums to find positions, then place each value directly. No comparisons — just counting!

🧮

Imagine tallying votes!

You have a stack of ballots, each with a number 0–8. Instead of comparing ballots to each other, you make a tally chart: count how many 0s, how many 1s, how many 2s... Then just write them out in order. No comparisons needed — just counting! That's counting sort.

▶️

Press PLAY to start counting sort!

// READY

INPUT

4
2
2
8
3
3
1
0
4
6
3
2

COUNT[]

0
0
1
0
2
0
3
0
4
0
5
0
6
0
7
0
8
0

OUTPUT

ACTIVE
VALUE
COUNT > 0
PLACED

// HOW IT WORKS — 3 PHASES

🔢PHASE 01

Count

Scan the input. For each value, increment count[value]. After this, count[i] = how many times i appears.

PHASE 02

Prefix sums

Convert counts to positions: count[i] += count[i-1]. Now count[i] = how many values are ≤ i.

📦PHASE 03

Place

Iterate input right-to-left. For each value, decrement count, place at that position. Stable!

💡

When is counting sort O(n)?

When k (the value range) is O(n) — i.e., the range of values is comparable to the number of elements. If k is much larger than n (e.g., sorting 10 numbers with values up to 1 billion), counting sort becomes O(k) which is terrible. That's where radix sort comes in!

// FLOWCHART · ALGORITHM VISUALIZATION

// FLOWCHART · Counting Sort
Sort [4, 2, 2, 8, 3, 3, 1] in O(n + k) time
array = [4, 2, 2, 8, 3, 3, 1] · k = 8
YesNoStartk ← max(array)count[0..k] ← 0count[array[i]]++for each icount[i] +=count[i-1]for i = 1..ki ← n - 1i ≥ 0 ?output[count[array[i]] - 1]← array[i]count[array[i]]--i ← i - 1array ← outputEnd

Press PLAY to trace the algorithm through the flowchart.

0 / 29

// PSEUDOCODE · EXECUTION FLOW

// PSEUDOCODE · Counting Sort
Sort in O(n + k) without comparisons
array = [4, 2, 2, 8, 3, 3, 1] · k = 8
1function countingSort(array):
2k ← max(array)
3count[0..k] ← 0
4for i from 0 to n-1:
5count[array[i]] ← count[array[i]] + 1
6for i from 1 to k:
7count[i] ← count[i] + count[i-1]
8for i from n-1 down to 0:
9output[count[array[i]] - 1] ← array[i]
10count[array[i]] ← count[array[i]] - 1
11return output

Press PLAY to step through the algorithm line by line.

0 / 12

// METHOD 2 · O(d · n)

Radix Sort
(LSD).

Sort numbers digit by digit, starting from the least significant (ones place). Each pass uses a stable sort (like counting sort) on one digit. After d passes, the array is fully sorted.

📇

Imagine sorting cards by each digit!

You have cards with numbers like 170, 45, 802. First, sort them by the LAST digit (ones place). Then sort by the tens place. Then hundreds. After each pass, the cards stay in relative order. After all passes — they're fully sorted! That's LSD Radix Sort.

▶️

Press PLAY to start radix sort!

// READY

ARRAY

ACTIVE BUCKET
ARRAY VALUE
IN BUCKET

// HOW IT WORKS — DIGIT BY DIGIT

1️⃣PASS 01

Ones place

Distribute into buckets 0–9 by the last digit. Collect in order.

2️⃣PASS 02

Tens place

Distribute by the tens digit. The array stays sorted by ones within each bucket.

3️⃣PASS 03

Hundreds

Repeat for each digit position. Each pass preserves the order from previous passes.

PASS 04

Done

After d passes (d = number of digits in the max value), the array is fully sorted.

💡

Why must each pass be STABLE?

Because we sort by one digit at a time. If a later pass breaks the order established by an earlier pass, the final result is wrong. A stable sort preserves the relative order of elements with the same digit — so the work of previous passes is never undone.

// FLOWCHART · ALGORITHM VISUALIZATION

// FLOWCHART · Radix Sort (LSD)
Sort [170, 45, 75, 90, 802, 24, 2, 66] digit by digit
array = [170, 45, 75, 90, 802, 24, 2, 66] · d = 3 digits
YesNoStartd ← count digitsin max(array)digit ← 0digit < d ?Stable sort bycurrent digit(counting sorton digit)digit ← digit + 1Return sortedarrayEnd

Press PLAY to trace the algorithm through the flowchart.

0 / 14

// PSEUDOCODE · EXECUTION FLOW

// PSEUDOCODE · Radix Sort (LSD)
Sort integers digit by digit, least significant first
array = [170, 45, 75, 90, 802, 24, 2, 66] · d = 3 digits
1function radixSort(array):
2d ← count digits in max(array)
3for digit from 0 to d - 1:
4exp ← 10^digit
5stableSortByDigit(array, exp)
6return array
7
8function stableSortByDigit(array, exp):
9count[0..9] ← 0
10for i from 0 to n-1:
11digit ← (array[i] / exp) mod 10
12count[digit] ← count[digit] + 1
13for i from 1 to 9:
14count[i] ← count[i] + count[i-1]
15for i from n-1 down to 0:
16digit ← (array[i] / exp) mod 10
17output[count[digit] - 1] ← array[i]
18count[digit] ← count[digit] - 1
19return output

Press PLAY to step through the algorithm line by line.

0 / 13

// TRY IT YOURSELF

Sort any
array in O(n).

Enter your own non-negative integers and sort them with counting sort. See the input, output, and the exact time complexity for your data.

// COUNTING_SORT.exe

// COMPLEXITY COMPARISON

Linear vs
comparison sorts.

Drag the slider to change N. See how comparison sorts grow as n log n while linear sorts grow linearly. The gap widens dramatically for large inputs.

// COMPLEXITY · N = 1,000, K = 100
100N = 1,000100K
COMPARISON SORTSO(n log n)

merge sort, quicksort, heapsort

COUNTING SORTO(n + k)

k = value range

RADIX SORTO(d · n)

d = number of digits

For n=1,000: comparison sorts need ~9,966 ops, counting sort needs ~1,100, radix sort needs ~3,000. That's 9× faster with counting sort!

// ALGORITHM COMPARISON
AlgorithmBestAverageWorstStable?
Counting SortO(n+k)O(n+k)O(n+k)Yes
Radix SortO(d·n)O(d·n)O(d·n)Yes (LSD)
Bucket SortO(n+k)O(n+k)O(n²)Yes
QuicksortO(n log n)O(n log n)O(n²)No
Merge SortO(n log n)O(n log n)O(n log n)Yes
HeapsortO(n log n)O(n log n)O(n log n)No

// PROPERTIES

4 things to
know about them.

No comparisons

Linear sorts don't compare elements to each other. They exploit the structure of the data (digits, value range) to sort directly.

O(n) when conditions met

Counting sort is O(n + k). Radix sort is O(d·n). Bucket sort is O(n) average. All beat the O(n log n) comparison-sort barrier — but only under the right conditions.

Stable by design

Counting sort and LSD radix sort are stable — equal elements keep their original relative order. This is crucial when sorting by multiple keys.

Not general-purpose

They only work on specific data types: non-negative integers with a small range (counting), fixed-width integers (radix), or uniformly distributed values (bucket).

// DID_YOU_KNOW

Fun facts about
linear sorting.

01

Counting sort was invented for punch cards

Harold Seward described counting sort in 1954 for sorting punched cards on early computing machinery — making it one of the oldest sorting algorithms.

02

Radix sort powered early computers

In the 1950s–60s, radix sort was the standard sorting method on mainframe computers because it matched how card-sorting machines physically worked.

03

The n log n barrier is real — for comparisons

Any sort that compares elements needs at least Ω(n log n) comparisons. Linear sorts escape this by NOT comparing — they use the data's internal structure instead.

04

Counting sort can sort 10 million items instantly

If values range 0–100, counting sort does ~10M + 101 operations. A comparison sort would need ~10M × 23 ≈ 230M. That's 23× slower.

05

Radix sort is the basis of MSD string sort

The same digit-by-digit idea extends to characters. Most-recent versions of Java's Arrays.sort() for primitives use dual-pivot quicksort, but for objects use TimSort — a stable hybrid.

06

Bucket sort loves uniform data

If your data is uniformly distributed (like random floats 0–1), bucket sort scatters values into n buckets and sorts each. Average case: O(n). Worst case (all in one bucket): O(n²).

// TUTORIAL QUIZZES · LEVELS 1–9

Test your mastery

Nine progressive quizzes from Level 1 to Level 9. Each has 10 questions with a 10-minute timer. XP scales with level — L1 gives 10 XP, L9 gives 90 XP. Click a quiz to expand and begin.

// REFERENCES

Sources & further reading

  1. [1]
    Introduction to Algorithms (CLRS)T. H. Cormen et al. — Chapters on sorting and order statistics
  2. [2]
    The Art of Computer Programming, Vol. 3Donald Knuth — Section 5.2: internal sorting
  3. [3]
    AlgorithmsRobert Sedgewick & Kevin Wayne — sorting algorithms and complexity
  4. [4]
    Sorting Out Sorting Ronald Baecker — classic visual comparison of sorting algorithms
  5. [5]
    Algorithm Design ManualSteven Skiena — practical sorting algorithm selection

// READY?

Master algorithms
with CodeTikki.

Practice 10,000+ coding problems, follow career roadmaps, and get hired.