ma'am audrey's lessons

ITC 120 › Final › Sorting

Sorting algorithms · Lesson 1 of 2

Basic Sorting: Bubble, Selection, and Insertion Sort

This lesson teaches:Algorithm

Three simple ways to put values in order, how to trace each one by hand, and how much work each one does.

By the end, you can:

  1. explain what a sorting algorithm does, and what comparison, swap, and pass mean;
  2. trace bubble sort, selection sort, and insertion sort by hand, writing the array after every pass;
  3. read, fix, and complete the three sorts in Java;
  4. compare their work (comparisons and swaps), the extra memory they need, and their stability, and choose one for a situation.

You need: the Arrays lesson (index, traversal, shifting), the Programming refresher (loops, &&, methods), and scratch paper.

Part 1 · The idea

Putting things in order

A teacher checks five quiz papers and wants them from the lowest score to the highest, to see first who needs help. A person can do this by looking. A program has to do it with exact steps.

Checked quiz papers (scores out of 40)1. As you collected themJoy29Ben10Paz14Mia37Cris13sort by score2. Sorted: lowest score firstBen10Cris13Paz14Joy29Mia37smallest to largest = ascending order
The same five papers, before and after sorting by score.

Sorting algorithm

A sorting algorithm is an algorithm (a step-by-step process) that puts the values of a collection in order: smallest to largest, A to Z, oldest to newest, and so on.

Here are the words that come with sorting:

WordMeaningWith the quiz papers
ascendingsmallest first, going up10, 13, 14, 29, 37
descendinglargest first, going down37, 29, 14, 13, 10
comparisonchecking two values to see which is bigger"Is 29 more than 10?"
swaptwo values trade placesJoy's paper and Ben's paper trade places
passone trip through the valuesgoing through the pile once, from first to last

In this lesson, every sort puts an array of ints in ascending order (smallest first), and all three sort in place: they rearrange the values inside the same array, without making a second one. Part 9 shows how to get descending order.

Where you see sorting in IT

  • "Sort by price: low to high" in an online shop.
  • A class list in A-to-Z order, or a grade sheet ranked by score.
  • Files sorted by name or by date modified in your phone's file manager.
  • Fast searching. The fastest way to search a list, binary search (in the Searching lesson), only works on sorted values.

This lesson teaches three basic sorts. They are easy to trace and to code, so they are the best place to learn how sorting works. The next lesson, Advanced sorting, shows faster ones for big data.

Part 2 · Two tools first

Swapping, and loops inside loops

All three sorts use two small coding tools that you have not met yet. Learn them here first.

Tool 1: swapping two values

Think of two glasses: one with calamansi juice, one with Milo. To swap the drinks, you need a third, empty glass.

Swap the drinks in glass A and glass Bglass Acalamansiglass BMiloextra glass(temp)1231. Pour A into the extra glass. 2. Pour B into A.3. Pour the extra glass into B.No extra glass = one drink gets mixed away.
Three pours, with an extra glass to hold one drink for a moment.

Swap

To swap two values is to make them trade places. In code it takes three lines and a helper variable, usually called temp (short for "temporary"), that holds one value for a moment so it is not lost.

Here is the swap of arr[j] and the slot after it, arr[j + 1]. You will see these three lines in every sort in this lesson:

 1int temp = arr[j];      // 1. save the left value
 2arr[j] = arr[j + 1];     // 2. copy the right value to the left
 3arr[j + 1] = temp;       // 3. put the saved value on the right
arr[j]arr[j+1]temp2910start291029int temp = arr[j];1101029arr[j] = arr[j + 1];2102929arr[j + 1] = temp;3Swapped: 10, 29. temp kept 29 safe.
Line 1 copies 29 into temp. Line 2 copies 10 over the 29 in the array. Line 3 copies the saved 29 into the second slot.

Mistake: swapping without temp

Situation: a student skips the helper variable:

arr[j] = arr[j + 1];     // the left value is overwritten...
arr[j + 1] = arr[j];     // ...so this copies the same value back
arr[j]arr[j+1]2910start1010arr[j] = arr[j + 1];11010arr[j + 1] = arr[j];229 is gone: both slots hold 10.
The first line overwrites 29 before it is saved anywhere.

What goes wrong: after the first line, both slots hold 10. The second line copies 10 onto 10. The 29 is lost for good, like pouring the Milo into the juice.

Fix: save one value in temp first, then copy, then put temp back.

Tool 2: a loop inside a loop

Your class schedule has days, and each day has periods. For each day, you go through all its periods before the next day starts.

Nested loop

A nested loop is a loop inside another loop. The inner loop runs all the way through, from start to end, every time the outer loop goes around once.

Here is the schedule as code, with 2 days of 3 periods each:

 1for (int day = 1; day <= 2; day++) {
 2  for (int period = 1; period <= 3; period++) {
 3    System.out.println("Day " + day + ", period " + period);
 4  }
 5}

▶ This program runs as is. Try it in the Programiz online compiler: tap Copy, paste it there, and press Run.

It prints six lines. Read the output from top to bottom and watch which number changes faster:

Day 1, period 1
Day 1, period 2
Day 1, period 3
Day 2, period 1
Day 2, period 2
Day 2, period 3

The inner variable (period) goes 1, 2, 3 for each value of the outer variable (day). In total, the inner loop body runs 2 × 3 = 6 times.

In the sorts, the outer loop counts the passes and the inner loop does the comparisons inside one pass.

Part 3 · Sort 1

Bubble sort: neighbors swap

Picture a class lining up by height for the flag ceremony, with no teacher arranging them. Each student only looks at the one beside them:

Line up by height for the flag ceremonytaller on the left→ switch placesEach pair of neighbors does this, left to right.After one walk down the line, the tallest is last.
If the one on the left is taller, the two switch places. The tallest keeps moving right until the end of the line.

Bubble sort

Bubble sort compares each pair of neighbors (side-by-side values) from left to right, and swaps them when the left one is bigger. One pass carries the biggest unsorted value to the end, like a bubble rising to the top of water. It repeats the passes until everything is in order.

By hand, it follows these steps:

  1. Compare the values at index 0 and 1. If the left one is bigger, swap them.
  2. Move one step right (index 1 and 2) and do the same. Keep going to the end. That is one pass, and the biggest value is now last.
  3. Do another pass, but stop before the values already in place at the end.
  4. With n values, after n - 1 passes the array is sorted.

Step through it on the five quiz scores. Orange cells are being compared; green cells are in their final place:

Bubble sort on 29, 10, 14, 37, 13, by hand

Use Next to go through the steps.

comparisons: 0swaps: 0290101142373134

Bubble sort on 29, 10, 14, 37, 13. Compare each pair of neighbors, left to right. If the left one is bigger, swap them.

Step 1 of 12

On paper (and on exams), write the array after each pass. Bold values are in their final place:

AfterArraySwaps
start29 10 14 37 13
pass 110 14 29 13 373
pass 210 14 13 29 371
pass 310 13 14 29 371
pass 410 13 14 29 370

Notice that each pass needs one comparison fewer than the pass before: 4, then 3, 2, 1. The values at the end are already in place, so there is no need to compare them again.

Bubble sort in Java

The outer loop counts the passes and the inner loop compares the neighbors, just like the in Part 2. The method is : it changes the array itself and gives nothing back.

Walkthrough: bubbleSort on 29, 10, 14, 37, 13

Use Next to go step by step, or tap a line to jump to it.

comparisons: 0swaps: 0290101142373134

n = 5

We call bubbleSort(arr) on the five scores. n is the number of values: 5. The method is void: it gives nothing back; it changes the array itself.

Step 1 of 14
 1static void bubbleSort(int[] arr) { 2  int n = arr.length; 3  for (int i = 0; i < n - 1; i++) {          // one pass 4    for (int j = 0; j < n - 1 - i; j++) {    // each pair of neighbors 5      if (arr[j] > arr[j + 1]) { 6        int temp = arr[j];                   // swap them 7        arr[j] = arr[j + 1]; 8        arr[j + 1] = temp; 9      }10    }11  }12}

Here is how to read the important lines aloud:

CodeRead it as
for (int i = 0; i < n - 1; i++)"do n - 1 passes." Five values need four passes.
for (int j = 0; j < n - 1 - i; j++)"walk along the neighbors, but skip the i values already in place at the end."
if (arr[j] > arr[j + 1])"if this value is bigger than its right neighbor..." (then swap them).

Mistake: comparing past the end of the array

Situation: a student writes the inner loop as j < n:

for (int j = 0; j < n; j++) {        // should be j < n - 1 - i
  if (arr[j] > arr[j + 1]) {
100141292133374?5jj+1arr[5] does not exist: ArrayIndexOutOfBoundsException
When j is 4, the code reads arr[j + 1], which is arr[5]. Five values only have indexes 0 to 4.

What goes wrong: every comparison also reads the next slot. The last value has no right neighbor, so Java stops the program with an ArrayIndexOutOfBoundsException (an error for using an index that does not exist).

Fix: stop one early: j < n - 1 - i (or at least j < n - 1).

Stopping early

Look at pass 4 in the table above: no swaps at all. A pass with no swaps means every neighbor is already in order, so the array is sorted and the remaining passes are wasted work. Many books add a boolean (true or false) variable to stop early:

 1static void bubbleSort(int[] arr) {
 2  int n = arr.length;
 3  for (int i = 0; i < n - 1; i++) {
 4    boolean swapped = false;               // no swaps yet in this pass
 5    for (int j = 0; j < n - 1 - i; j++) {
 6      if (arr[j] > arr[j + 1]) {
 7        int temp = arr[j];
 8        arr[j] = arr[j + 1];
 9        arr[j + 1] = temp;
10        swapped = true;
11      }
12    }
13    if (!swapped) {
14      break;                               // a pass with no swaps: sorted, stop
15    }
16  }
17}

!swapped reads "not swapped" (! flips true and false). On an array that is already sorted, this version makes one pass of n - 1 comparisons and stops. The plain version above still makes all of them. This lesson's walkthroughs and lab use the plain version.

Part 4 · Sort 2

Selection sort: pick the smallest

Back to the . This time, the teacher looks over everyone who is not yet placed, calls the shortest one to the front, then the shortest of those left, and so on. Every call places one student for good.

Selection sort

Selection sort splits the array into a sorted part (on the left) and an unsorted part. Each pass selects the smallest value in the unsorted part and swaps it to the front of that part, which makes the sorted part one value longer.

By hand:

  1. Look at every value from index 0 to the end, and remember where the smallest one is.
  2. Swap that smallest value with the value at index 0. Index 0 is now final.
  3. Do the same for index 1 to the end, and swap the smallest into index 1. Then index 2, and so on.
  4. After n - 1 passes, the last value is also in place.

Step through it on the same scores. The yellow cell is the smallest so far:

Selection sort on 29, 10, 14, 37, 13, by hand

Use Next to go through the steps.

comparisons: 0swaps: 0290101142373134

Selection sort on 29, 10, 14, 37, 13. Each pass finds the smallest value in the unsorted part and swaps it to the front of that part.

Step 1 of 16

Here is the table for selection sort. Bold values are final:

AfterSmallest foundArray
start29 10 14 37 13
pass 110 (swap with 29)10 29 14 37 13
pass 213 (swap with 29)10 13 14 37 29
pass 314 (already there)10 13 14 37 29
pass 429 (swap with 37)10 13 14 29 37

Bubble sort puts the biggest value in place at the end of each pass. Selection sort puts the smallest in place at the front.

Selection sort in Java

The variable minIndex remembers where the smallest value so far is. The swap happens only once per pass, after the inner loop:

 1static void selectionSort(int[] arr) {
 2  int n = arr.length;
 3  for (int i = 0; i < n - 1; i++) {
 4    int minIndex = i;                   // smallest so far
 5    for (int j = i + 1; j < n; j++) {
 6      if (arr[j] < arr[minIndex]) {
 7        minIndex = j;                   // found a smaller one
 8      }
 9    }
10    int temp = arr[i];                  // swap it to the front
11    arr[i] = arr[minIndex];
12    arr[minIndex] = temp;
13  }
14}

Each pass of the outer loop (line 3) does what one pass did in the steps above. Lines 4 to 9 look through the unsorted part for the smallest value, and lines 10 to 12 are the swap from Part 2, done once at the end of the pass.

Here is how to read the important lines aloud:

CodeRead it as
int minIndex = i;"to start, assume the first unsorted value is the smallest."
for (int j = i + 1; j < n; j++)"look at every value after it, to the end."
if (arr[j] < arr[minIndex])"if this value is smaller than the smallest so far..." (then remember its index).
Step through the code line by line (optional)

The same five scores as the steps above, now with the code: each step lights up the line that runs and shows i, j, and minIndex.

Walkthrough: selectionSort on 29, 10, 14, 37, 13

Use Next to go step by step, or tap a line to jump to it.

comparisons: 0swaps: 0290101142373134

n = 5

We call selectionSort(arr) on the same five scores. n = 5.

Step 1 of 12
 1static void selectionSort(int[] arr) { 2  int n = arr.length; 3  for (int i = 0; i < n - 1; i++) { 4    int minIndex = i;                   // smallest so far 5    for (int j = i + 1; j < n; j++) { 6      if (arr[j] < arr[minIndex]) { 7        minIndex = j;                   // found a smaller one 8      } 9    }10    int temp = arr[i];                  // swap it to the front11    arr[i] = arr[minIndex];12    arr[minIndex] = temp;13  }14}

Mistake: comparing with arr[i] instead of the smallest so far

Situation: a student compares each value with the first unsorted value:

if (arr[j] < arr[i]) {       // should be arr[minIndex]
  minIndex = j;
}
290101142373134imin10, 14, 13 are all smaller than 29; the LAST one wins130101142373294i13 goes to the front, but 10 is smaller: wrong!
Top: 10, 14, and 13 are all smaller than 29, and each one replaces minIndex. Bottom: the last of them, 13, is swapped to the front.

What goes wrong: the code finds the last value smaller than 29, not the smallest. 13 lands at index 0 even though 10 is smaller, so the array does not end up sorted.

Fix: always compare with the smallest found so far: arr[j] < arr[minIndex].

Part 5 · Sort 3

Insertion sort: like cards in your hand

When you play tong-its and pick up a new card, you do not re-sort your whole hand. You slide it into the right spot among the cards you already arranged:

Tong-its: adding a new card to your hand6♥new card2♥5♥gap8♥10♥bigger cards slide rightThe hand stays in order. Drop the 6 into the gap.
The bigger cards slide right to make a gap, and the new card drops in.

Insertion sort

Insertion sort keeps a sorted part on the left, starting with just the first value. Each pass takes the next value, called the key, shifts the bigger sorted values one slot right, and inserts the key into the gap.

The moving step is the same you used to insert into an array. By hand:

  1. Treat index 0 alone as sorted.
  2. Take the next value (the key) out of the array. Its slot is now a gap.
  3. Going left, shift every sorted value that is bigger than the key one slot right.
  4. Stop at a value that is not bigger, or at the start of the array. Drop the key into the gap.
  5. Repeat for every value to the end.

Insertion sort on 29, 10, 14, 37, 13, by hand

Use Next to go through the steps.

comparisons: 0shifts: 0290101142373134

Insertion sort on 29, 10, 14, 37, 13. The first value alone counts as a sorted part (green). Each pass takes the next value, the key, and inserts it into the sorted part.

Step 1 of 15

Here is the table. The green part of each row is the sorted part so far:

AfterKeyArrayShifts
start29 10 14 37 13
pass 11010 29 14 37 131
pass 21410 14 29 37 131
pass 33710 14 29 37 130
pass 41310 13 14 29 373

Careful: in insertion sort, bold means "sorted so far", not "final". In pass 4, 14, 29, and 37 still moved. In bubble and selection sort, a bold value never moves again.

Insertion sort in Java

The shifting uses a while loop with two conditions joined by :

 1static void insertionSort(int[] arr) {
 2  for (int i = 1; i < arr.length; i++) {
 3    int key = arr[i];                   // the value to insert
 4    int j = i - 1;
 5    while (j >= 0 && arr[j] > key) {
 6      arr[j + 1] = arr[j];              // shift the bigger value right
 7      j--;
 8    }
 9    arr[j + 1] = key;                   // drop key into the gap
10  }
11}

Each pass of the for loop (line 2) does what one pass did in the steps above. Lines 3 and 4 take out the key and point j at the value on its left. The while loop (lines 5 to 8) shifts the bigger values right, and line 9 drops the key into the gap.

Here is how to read the important lines aloud:

CodeRead it as
int key = arr[i];"take out the value to insert, so its slot can be a gap."
while (j >= 0 && arr[j] > key)"while there is still a value on the left, and it is bigger than the key..."
arr[j + 1] = arr[j];"shift that value one slot right." The gap moves one slot left.
arr[j + 1] = key;"drop the key into the gap." (j stopped one slot left of the gap.)
Step through the code line by line (optional)

The same five scores as the steps above, now with the code: each step lights up the line that runs and shows key and j.

Walkthrough: insertionSort on 29, 10, 14, 37, 13

Use Next to go step by step, or tap a line to jump to it.

comparisons: 0shifts: 0290101142373134

We call insertionSort(arr) on the same scores. The first value, 29, alone is already a sorted part (green), so the loop starts at index 1.

Step 1 of 13
 1static void insertionSort(int[] arr) { 2  for (int i = 1; i < arr.length; i++) { 3    int key = arr[i];                   // the value to insert 4    int j = i - 1; 5    while (j >= 0 && arr[j] > key) { 6      arr[j + 1] = arr[j];              // shift the bigger value right 7      j--; 8    } 9    arr[j + 1] = key;                   // drop key into the gap10  }11}

Mistake: the two checks in the wrong order

Situation: a student swaps the two sides of &&:

while (arr[j] > key && j >= 0) {    // the two checks are in the wrong order
key = 100291142373134?-1jarr[-1] is read before j >= 0 is checked: crash
After 29 shifts right, j is -1. The condition now starts with arr[-1].

What goes wrong: Java checks the left side of && first. Here that is arr[j] > key, so when j is -1 it reads arr[-1], which does not exist, and the program stops with an ArrayIndexOutOfBoundsException.

Fix: put j >= 0 first. When it is false, && already knows the answer is false and skips the right side, so arr[-1] is never read.

Part 6 · Try it

The sort lab

Run all three sorts on the same array and count the work. Try the quiz scores first, then already sorted (which sort notices?), then reversed (the worst case), then your own numbers from the practice in Part 10.

Sort lab

Pick an array, then a sort. Use Next step to watch every comparison. At the end, the lab shows how much work all three sorts need for the same array.

Arrays:

Step 0 of 0
comparing now just moved smallest so far in sorted part gap

Part 7 · Why this matters

How much work does each sort do?

We measure the work of a sort by counting two things: comparisons (checking two values) and moves (swaps, or shifts in insertion sort). Here are the counts for five values, from the lab (and from running the Java code):

ArrayBubbleSelectionInsertion
quiz scores 29 10 14 37 1310 comparisons, 5 swaps10 comparisons, 4 swaps8 comparisons, 5 shifts
already sorted 10 13 14 29 3710 comparisons, 0 swaps10 comparisons, 4 swaps4 comparisons, 0 shifts
reversed 37 29 14 13 1010 comparisons, 10 swaps10 comparisons, 4 swaps10 comparisons, 10 shifts

Why 10 comparisons? Each pass compares one value fewer than the pass before. That makes a staircase:

Comparisons for 5 values (bubble or selection)pass 14 comparisonspass 23 comparisonspass 32 comparisonspass 41 comparison4 + 3 + 2 + 1 = 10 comparisonsFor 1,000 values: 999 + 998 + … + 1 = 499,500
4 + 3 + 2 + 1 = 10. In general, n values need about n × n / 2 comparisons.

Five values is nothing. But the staircase grows fast. Here is the number of comparisons for our bubble sort and selection sort:

Number of valuesComparisons
1045
1004,950
1,000499,500
1,000,000about 500,000,000,000 (500 billion)

Look at the pattern: 10 times more values means about 100 times more work, and twice as many values means about four times the work. That is fine for a class list of 40 students, but far too slow for a million GCash transactions. The sorts in the next lesson handle a million values in about 20 million comparisons.

Here is a summary of the best and worst cases for n values:

SortComparisonsMoves
Bubble (plain)always about n × n / 20 (sorted) to about n × n / 2 (reversed)
Bubble (stop early)n - 1 when already sorted; about n × n / 2 at worstsame as plain
Selectionalways about n × n / 2, even when sortedalways n - 1 swaps: few, even in the worst case
Insertionn - 1 when already sorted; about n × n / 2 when reversed0 (sorted) to about n × n / 2 (reversed)

Two things stand out. Insertion sort is very fast when the data is already almost sorted, because each key moves only a little. Selection sort always makes the same number of comparisons, but very few swaps, which helps when moving a value is costly (for example, big records).

Good to know: books describe this growth with short names. All three sorts are O(n²) ("order n squared") in the worst case: the work grows with n × n. Insertion sort (and bubble sort with the early stop) is O(n) in the best case, an already sorted array. You met in the searching lesson.

How much memory does each sort need?

Time is one cost. The other is memory: how much extra computer storage a sort needs while it works. Books call this its space.

All three sorts here work in place (Part 1): they move the values around inside the same array. Besides the array, they only need a few single variables: temp for the swap, minIndex (selection) or key (insertion), and the loop counters i and j. Five values or a million, it is the same handful of variables, so the extra memory does not grow with n.

Good to know: books write this as O(1) extra space ("constant space": the same small amount for any n). Merge sort, in the next lesson, is different: it needs a second array as big as the first.

Part 8 · Ties

Stable sorting

Real data is often a record: a name and a grade, not just a number. The class list is already in A-to-Z order. The teacher now sorts it by grade, lowest first, to see who needs help. Ana and Ben both have 85. Should Ana still come before Ben?

Most people expect yes: when two grades tie, the old A-to-Z order should stay. A sort that keeps it is called stable.

Stable sort

A sorting algorithm is stable when values that are equal (by what we sort on) keep the order they had before sorting.

Start: A to ZAna85Ben85Cris80Stable (insertion, bubble): Ana still before BenCris80Ana85Ben85Not stable (selection): Ben jumped ahead of AnaCris80Ben85Ana85
Sorting the A-to-Z list by grade. Insertion and bubble sort keep Ana before Ben; selection sort does not.

Why the difference?

  • Bubble sort and insertion sort only move a value past a neighbor that is strictly bigger (>). Equal values never pass each other, so their order stays.
  • Selection sort swaps across a long distance. In pass 1 here, the smallest grade (Cris, 80) is at the end. Swapping it with Ana at the front throws Ana to the end, past Ben. Ties can change order.

Mistake: >= instead of > in bubble sort

Situation: a student writes if (arr[j] >= arr[j + 1]).

What goes wrong: the array still ends up sorted, but equal neighbors now swap too. That is wasted work, and Ana and Ben trade places, so the sort is no longer stable.

Fix: swap only when the left value is strictly bigger: >. The same goes for insertion sort's arr[j] > key.

Good to know: for plain ints, stability does not matter, because two equal numbers look exactly the same. It matters when you sort records, like students by grade or orders by date. Java's own sort for objects is stable.

Part 9 · Choosing

Which sort, and Java's own sort

Here are the three sorts side by side:

BubbleSelectionInsertion
Ideaneighbors swap; the biggest moves to the endfind the smallest; swap it to the fronttake the next value; insert it into the sorted part
Comparisonsabout n × n / 2about n × n / 2, alwaysn - 1 to about n × n / 2
Movesmanyfew: n - 1 swaps, even in the worst casemany, but few on almost-sorted data
Stable?yesnoyes

And here is how to choose among them:

SituationGood choice
A list that is almost sorted already, like a class list where a few late enrollees were added at the endInsertion sort
New values arrive one at a time and the list must stay sorted, like cards dealt to your handInsertion sort
Moving (writing) a value is very costly, so swaps must be fewSelection sort
Records with ties whose order must stayInsertion sort (stable)
Learning and tracing by handBubble sort (simplest idea), but rarely the best in real programs
Large data in a real programnone of these: use Java's Arrays.sort

All three in one program

Here are the three sorts in one runnable file. Run it, and match each output line to its comment:

 1import java.util.Arrays;
 2
 3public class Main {
 4  static void bubbleSort(int[] arr) {
 5    int n = arr.length;
 6    for (int i = 0; i < n - 1; i++) {
 7      for (int j = 0; j < n - 1 - i; j++) {
 8        if (arr[j] > arr[j + 1]) {
 9          int temp = arr[j];
10          arr[j] = arr[j + 1];
11          arr[j + 1] = temp;
12        }
13      }
14    }
15  }
16
17  static void selectionSort(int[] arr) {
18    int n = arr.length;
19    for (int i = 0; i < n - 1; i++) {
20      int minIndex = i;
21      for (int j = i + 1; j < n; j++) {
22        if (arr[j] < arr[minIndex]) {
23          minIndex = j;
24        }
25      }
26      int temp = arr[i];
27      arr[i] = arr[minIndex];
28      arr[minIndex] = temp;
29    }
30  }
31
32  static void insertionSort(int[] arr) {
33    for (int i = 1; i < arr.length; i++) {
34      int key = arr[i];
35      int j = i - 1;
36      while (j >= 0 && arr[j] > key) {
37        arr[j + 1] = arr[j];
38        j--;
39      }
40      arr[j + 1] = key;
41    }
42  }
43
44  public static void main(String[] args) {
45    int[] a = {29, 10, 14, 37, 13};
46    int[] b = {29, 10, 14, 37, 13};
47    int[] c = {29, 10, 14, 37, 13};
48    bubbleSort(a);
49    selectionSort(b);
50    insertionSort(c);
51    System.out.println(Arrays.toString(a));   // [10, 13, 14, 29, 37]
52    System.out.println(Arrays.toString(b));   // [10, 13, 14, 29, 37]
53    System.out.println(Arrays.toString(c));   // [10, 13, 14, 29, 37]
54  }
55}

▶ This program runs as is. Try it in the Programiz online compiler: tap Copy, paste it there, and press Run.

Sorting with Java's Arrays

In real programs, you rarely write a sort yourself. Arrays.sort sorts an array of numbers, or of Strings in A-to-Z order, and it uses faster methods like the ones in the next lesson. It lives in java.util.Arrays, so the file starts with an import line.

 1import java.util.Arrays;
 2
 3public class Main {
 4  public static void main(String[] args) {
 5    int[] scores = {29, 10, 14, 37, 13};
 6    Arrays.sort(scores);
 7    System.out.println(Arrays.toString(scores));   // [10, 13, 14, 29, 37]
 8
 9    String[] names = {"Mia", "Ben", "Joy", "Ana"};
10    Arrays.sort(names);                             // A to Z
11    System.out.println(Arrays.toString(names));    // [Ana, Ben, Joy, Mia]
12
13    // Highest first: read the sorted array from the end.
14    for (int i = scores.length - 1; i >= 0; i--) {
15      System.out.print(scores[i] + " ");           // 37 29 14 13 10
16    }
17    System.out.println();
18  }
19}

▶ This program runs as is. Try it in the Programiz online compiler: tap Copy, paste it there, and press Run.

Three things to notice:

  • Arrays.sort is void, like our sorts: it changes the array itself.
  • It always sorts in ascending order. For highest first, read the sorted array from the end (lines 14 to 16).
  • For Strings, capital letters come before small letters: "Zed" comes before "ana". Keep names in the same case.

Part 10 · Your turn

Practice

On paper

Use the array {6, 2, 9, 1, 5} for questions 1 to 3. Check your tables with the sort lab: type the numbers under "Or type your own".

  1. Bubble sort: write the array after each pass. How many swaps in total?
  2. Selection sort: write the array after each pass. In which passes does the smallest value "swap" with itself?
  3. Insertion sort: write the array after each pass (the key for pass 1 is 2). How many shifts in total?
  4. Spot the bug. This method should sort the array, but {29, 10, 14, 37, 13} becomes {13, 10, 14, 29, 37}. Which line is wrong, and what should it be?
     1static void selectionSort(int[] arr) {
     2  for (int i = 0; i < arr.length - 1; i++) {
     3    int minIndex = i;
     4    for (int j = i + 1; j < arr.length; j++) {
     5      if (arr[j] < arr[i]) {
     6        minIndex = j;
     7      }
     8    }
     9    int temp = arr[i];
    10    arr[i] = arr[minIndex];
    11    arr[minIndex] = temp;
    12  }
    13}
  5. Which sort? (a) A grade sheet already in A-to-Z order, to be sorted by grade, with ties kept in A-to-Z order. (b) A list of 200 enrolled students in order, plus 3 late enrollees added at the end. (c) A memory where every write is slow, so you want as few swaps as possible.
Show the answers

For self-study, not for grading. All answers were checked by running the code in Java.

  1. AfterArraySwaps
    pass 12 6 1 5 93
    pass 22 1 5 6 92
    pass 31 2 5 6 91
    pass 41 2 5 6 90
    6 swaps in total, and 10 comparisons.
  2. AfterSmallest foundArray
    pass 11 (swap with 6)1 2 9 6 5
    pass 22 (already there)1 2 9 6 5
    pass 35 (swap with 9)1 2 5 6 9
    pass 46 (already there)1 2 5 6 9
    Passes 2 and 4 swap a value with itself.
  3. AfterKeyArrayShifts
    pass 122 6 9 1 51
    pass 292 6 9 1 50
    pass 311 2 6 9 53
    pass 451 2 5 6 92
    6 shifts in total, and 8 comparisons.
  4. Line 5. It compares with arr[i], so it finds the last value smaller than arr[i], not the smallest. It should be if (arr[j] < arr[minIndex]).
  5. (a) Insertion sort (or bubble sort): it must be stable, and selection sort is not. (b) Insertion sort: the list is almost sorted, so each late enrollee is shifted into place with little work. (c) Selection sort: only n - 1 swaps.

Your coding task: is it sorted?

Before sorting, a program can check whether the work is needed at all. Finish isSorted so it returns true when every value is less than or equal to the value after it, and false otherwise. It is one pass of bubble sort's comparisons, with no swaps. Write about 5 lines where it says YOUR CODE, then run it: the four printed values must match the comments.

 1public class Main {
 2  static boolean isSorted(int[] arr) {
 3    // YOUR CODE: compare each pair of neighbors.
 4    // If a value is bigger than the one after it, return false.
 5
 6    return true;
 7  }
 8
 9  public static void main(String[] args) {
10    System.out.println(isSorted(new int[] {10, 13, 14, 29, 37}));  // expected: true
11    System.out.println(isSorted(new int[] {10, 14, 13, 29, 37}));  // expected: false
12    System.out.println(isSorted(new int[] {5, 5, 8}));             // expected: true
13    System.out.println(isSorted(new int[] {42}));                  // expected: true
14  }
15}

▶ This program runs as is. Try it in the Programiz online compiler: tap Copy, paste it there, and press Run.

Show one possible answer
 1static boolean isSorted(int[] arr) {
 2  for (int i = 0; i < arr.length - 1; i++) {
 3    if (arr[i] > arr[i + 1]) {
 4      return false;
 5    }
 6  }
 7  return true;
 8}

Output: true, false, true, true. The loop stops at arr.length - 1 because each check also reads the next slot (the same reason as ). One value, or two equal values, count as sorted.

Part 11 · Check yourself

Self-check

Not graded. Tap an answer to see if you got it, and read why.

  1. Bubble sort (smallest first) finishes pass 1 on {29, 10, 14, 37, 13}. Where is 37 now?

  2. Why does a swap need temp?

  3. Selection sort (our code) on 5 values: how many times do the three swap lines run?

  4. Which basic sort needs the fewest comparisons on an array that is already sorted?

  5. In insertion sort, why is it j >= 0 && arr[j] > key and not the other way around?

  6. What does it mean when a sort is stable?

  7. Which of the three basic sorts is not stable?

  8. About how many comparisons does our bubble sort make on 1,000 values?

  9. Bubble sort on 1,000,000 values. How much extra memory does it need, besides the array?

Score: 0 / 9

Key takeaways

  1. A sorting algorithm puts values in order. We count its work in comparisons and moves (swaps or shifts).
  2. A swap needs a helper variable, temp, or one value is lost.
  3. Bubble sort: neighbors swap; each pass moves the biggest to the end. Selection sort: find the smallest, swap it to the front. Insertion sort: shift bigger values right, insert the key.
  4. All three need about n × n / 2 comparisons in the worst case. Insertion sort is fast on almost-sorted data; selection sort makes the fewest swaps.
  5. All three sort in place: besides the array, they need only a few variables, however big the array is.
  6. Bubble and insertion sort are stable (ties keep their order); selection sort is not.
  7. In real programs, use Arrays.sort.

Next lesson: Advanced sorting: merge sort, quick sort, and heap sort. After that: Hashing and hash tables, the last topic of the course.

References

  1. R. Sedgewick and K. Wayne, Algorithms, 4th ed. Addison-Wesley, 2011, Section 2.1 (elementary sorts, stability in 2.5). algs4.cs.princeton.edu
  2. A. Bhargava, Grokking Algorithms. Manning, 2016, Chapter 2 (selection sort).
  3. Programiz, "Bubble Sort," "Selection Sort," and "Insertion Sort." programiz.com/dsa
  4. Oracle, "Class Arrays," Java SE 21 API (sort; the sort for objects is stable). docs.oracle.com
  5. ITC 120 Course Syllabus (Sorting Algorithms: basic and advanced; compare stability and performance), Davao Oriental State University.