Advanced

Built-in sorts

The built-in sort is a tuned hybrid, not a textbook algorithm. It exploits runs already in the data, which is why sorting real data is faster than the worst case suggests.

What you will see

[3, 2, 1]

About 2 min of reading

Quick check

Before this new lesson, one small question about the lesson you just finished. Recall it, do not look it up.

Try It

Use the built-in sort.

1

Sort a row with a run.

nums = [1, 2, 3, 0, 9, 8] print(sorted(nums))

Before you run it, say out loud what it will print. Then open the answer.

What it prints
[0, 1, 2, 3, 8, 9]
2

Sort in place.

nums = [3, 1, 2] nums.sort() print(nums)

Before you run it, say out loud what it will print. Then open the answer.

What it prints
[1, 2, 3]
3

Sort words by length.

words = ["owlww", "ox", "bee"] print(sorted(words, key=len))

Before you run it, say out loud what it will print. Then open the answer.

What it prints
['ox', 'bee', 'owlww']
4

Sort descending.

nums = [1, 3, 2] print(sorted(nums, reverse=True))

Before you run it, say out loud what it will print. Then open the answer.

What it prints
[3, 2, 1]

Put it in order

Before you write anything, put these lines back in the right order. Click a line to move it up one step. This support step is easier than writing code from scratch, and it is here to make the last example stick.

Data Flow

The built-in sort is a tuned hybrid that exploits runs already in the data, is stable, and beats the worst case on real input.
1 find runs in data
↓
2 merge sorted runs
↓
3 insertion for short runs
↓
4 stable and tuned
Line by line

Read the first example one line at a time. A line that prints shows what appears on screen; the rest set things up quietly.

nums = [1, 2, 3, 0, 9, 8] sets nothing on screen
print(sorted(nums)) [0, 1, 2, 3, 8, 9]
Why this works
Hybrid is why it is fast

Timsort merges sorted runs it finds and uses insertion sort for short ones. Real data has runs, so it beats the worst case often.

Trust the library

A hand-written quicksort or merge sort is for learning. Production code calls the built-in sort, which is tuned and stable.

Examples

Timsort finds runs

nums = [1, 2, 3, 0, 9, 8]
print(sorted(nums))

The sort spots that 1,2,3 is already ordered and 9,8 is a reversed run. It uses those instead of starting over.

Nearly sorted is fast

nums = list(range(100))
nums[50], nums[51] = nums[51], nums[50]
print(nums == sorted(nums))

One swap out of place. The built-in sort fixes it cheaply because it works on runs.

Stable by default

rows = [(2, "a"), (2, "b")]
print(sorted(rows))

The built-in sort is stable. Ties keep input order, which the multi-field trick needs.

In place versus new

nums = [3, 1, 2]
nums.sort()
print(nums)

list.sort changes the list and returns nothing. sorted returns a new list. Same algorithm, two shapes.

Key is measured once

words = ["owlww", "ox", "bee"]
print(sorted(words, key=len))

The key runs once per item, then the sort orders the measures. An expensive key is paid once.

Reverse without a second sort

nums = [1, 3, 2]
print(sorted(nums, reverse=True))

The reverse flag flips the comparison. No second pass is needed.

Sort mixed types fails

print(sorted([2, "a"]))

Numbers and text cannot be compared. A key that maps both to one type is the fix.

Real data is easy

import random
nums = [random.randint(0, 100) for _ in range(50)]
print(sorted(nums) == sorted(nums))

Even random data sorts fast. The built-in sort is tuned for the mix of runs real data has.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← The cost of sorting
Previous Lesson
The cost of sorting
Next Lesson
Sorting records by several keys
Sorting records by several keys →