Selection sort repeatedly pulls the smallest remaining item into place. Insertion sort grows a sorted prefix by inserting the next item. Both are about n² comparisons.
Goal
Sort a price list both ways and print the comparisons.
Selection sort
def selection_sort(items):
xs = list(items)
steps = 0
n = len(xs)
for i in range(n):
lo = i
for j in range(i + 1, n):
steps += 1
if xs[j] < xs[lo]:
lo = j
xs[i], xs[lo] = xs[lo], xs[i]
return xs, steps
print(selection_sort([31, 10.5, 22.0, 10.5]))Insertion sort
def insertion_sort(items):
xs = list(items)
steps = 0
for i in range(1, len(xs)):
key = xs[i]
j = i - 1
while j >= 0:
steps += 1
if xs[j] > key:
xs[j + 1] = xs[j]
j -= 1
else:
break
xs[j + 1] = key
return xs, steps
print(insertion_sort([31, 10.5, 22.0, 10.5]))Insertion sort does fewer comparisons when the list is almost sorted. Selection sort always scans the suffix.
From a file
Download unsorted.txt, Add files, then:
from pathlib import Path
def selection_sort(items):
xs = list(items)
n = len(xs)
for i in range(n):
lo = i
for j in range(i + 1, n):
if xs[j] < xs[lo]:
lo = j
xs[i], xs[lo] = xs[lo], xs[i]
return xs
nums = [float(line) for line in Path("unsorted.txt").read_text(encoding="utf-8").splitlines() if line.strip()]
print(nums)
print(selection_sort(nums))Tip
sorted(xs) is the right tool in production. You are implementing the idea so the n² nested loops are visible.