Lecture 9:
Sorting Algorithms
TA: Geonhee Ahn�justamoment@ewhain.net
Insertion Sort in Life
The Great Dalmuti
2
Insertion Sort
3
Sorting Problem
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | 15 | 2 | 6 | -1 | 5 | 4 | 10 | -4 | 21 |
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | -4 | -1 | 2 | 4 | 5 | 6 | 10 | 15 | 21 |
4
Why Sorting?
5
(Human-like) Insertion Sort
Pile
Sorted list
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | 15 | 2 | 6 | -1 | 5 | 4 | 10 | -4 | 21 |
Index |
Value |
6
(Human-like) Insertion Sort
Pile
Sorted list
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | 15 | 2 | 6 | -1 | 5 | 4 | 10 | -4 | 21 |
Index | 0 |
Value | -7 |
7
(Human-like) Insertion Sort
Pile
Sorted list
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | 15 | 2 | 6 | -1 | 5 | 4 | 10 | -4 | 21 |
Index | 0 | 1 |
Value | -7 | 15 |
8
(Human-like) Insertion Sort
Pile
Sorted list
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | 15 | 2 | 6 | -1 | 5 | 4 | 10 | -4 | 21 |
Index | 0 | 1 | 2 |
Value | -7 | 2 | 15 |
9
(Human-like) Insertion Sort
Pile
Sorted list
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | 15 | 2 | 6 | -1 | 5 | 4 | 10 | -4 | 21 |
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
Value | -7 | -4 | -1 | 2 | 4 | 5 | 6 | 10 | 15 |
10
Insertion Sort
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | 15 | 2 | 6 | -1 | 5 | 4 | 10 | -4 | 21 |
Sorted
Unsorted
11
Insertion Sort
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | 15 | 2 | 6 | -1 | 5 | 4 | 10 | -4 | 21 |
Sorted
Unsorted
12
Insertion Sort
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | 15 | 2 | 6 | -1 | 5 | 4 | 10 | -4 | 21 |
Sorted
Unsorted
13
Insertion Sort
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | 2 | 15 | 6 | -1 | 5 | 4 | 10 | -4 | 21 |
Sorted
Unsorted
14
Insertion Sort
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | 2 | 6 | 15 | -1 | 5 | 4 | 10 | -4 | 21 |
Sorted
Unsorted
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | -4 | -1 | 2 | 4 | 5 | 6 | 10 | 15 | 21 |
Sorted
15
Insertion Sort: Implementation
def insertion_sort(list):
for i in range(1, len(list)):
key = list[i]
j = i - 1
while j >=0 and key < list[j]:
list[j+1] = list[j]
j -= 1
list[j+1] = key
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | -1 | 2 | 5 | 6 | 15 | 4 | 10 | -4 | 21 |
Sorted
i
key
j
16
Time Complexity
?
O(N)
O(N)
O(1)
Complexity?
O(log N) if binary search used.
O(N)
O(N2)
17
Selection Sort
18
Selection Sort
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | 15 | 2 | 6 | -1 | 5 | 4 | 10 | -4 | 21 |
Sorted
Unsorted
Find the smallest among unsorted ones.
The smallest is already in the target place 😀
19
Selection Sort
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | 15 | 2 | 6 | -1 | 5 | 4 | 10 | -4 | 21 |
Sorted
Unsorted
Find the smallest among unsorted ones.
Swap it with the one at the target position.
20
Selection Sort
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | -4 | 2 | 6 | -1 | 5 | 4 | 10 | 15 | 21 |
Sorted
Unsorted
Find the smallest among unsorted ones.
Swap it with the one at the target position.
21
Selection Sort
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | -4 | -1 | 6 | 2 | 5 | 4 | 10 | 15 | 21 |
Sorted
Unsorted
Find the smallest among unsorted ones.
Swap it with the one at the target position.
Repeat until there is no item left in the unsorted region!
22
Selection Sort: Implementation
def selection_sort(list):
for i in range(len(list)):
smallest = i
for j in range(i+1, len(list)):
if list[j] < list[smallest]:
smallest = j
list[i], list[smallest] = list[smallest], list[i]
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | -4 | -1 | 6 | 10 | 5 | 4 | 2 | 15 | 21 |
Sorted
i
smallest
swap
Q. Can you implement this with recursion?
23
Time Complexity
?
O(N)
O(1)
Complexity?
O(N)
O(N2)
24
Merge Sort
25
Announcement & Tentative Schedule
26
Motivation
27
Merge Sort
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Value | 5 | -2 | 0 | 10 | -6 | 7 | 4 | 9 |
Index | 0 | 1 | 2 | 3 |
Value | -2 | 0 | 5 | 10 |
Index | 0 | 1 | 2 | 3 |
Value | -6 | 4 | 7 | 9 |
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Value | -6 | -2 | 0 | 4 | 5 | 7 | 9 | 10 |
Sort
Sort
Merge
28
Merge Sort
Okay, dividing is easy!
Sorting each separately is also easy, as they have just a single item in the end.
5 | -2 | 0 | 10 | -6 | 7 | 4 | 9 |
5 | -2 | 0 | 10 |
-6 | 7 | 4 | 9 |
5 | -2 |
0 | 10 |
-6 | 7 |
4 | 9 |
5 |
-2 |
0 |
10 |
-6 |
7 |
4 |
9 |
29
Merge Sort
What about merging?!
-6 | -2 | 0 | 4 | 6 | 7 | 9 | 10 |
-2 | 0 | 5 | 10 |
-6 | 4 | 7 | 9 |
-2 | 5 |
0 | 10 |
-6 | 7 |
4 | 9 |
5 |
-2 |
0 |
10 |
-6 |
7 |
4 |
9 |
30
Merge Sort
-6 | -2 | 0 | 4 | 6 | 7 | 9 | 10 |
-2 | 0 | 5 | 10 |
-6 | 4 | 7 | 9 |
31
Merge Sort
The first (smallest) item must be either the smallest item in the left sublist or the smallest one in the right sublist.
-6
| | | | | | | |
-2 | 0 | 5 | 10 |
-6 | 4 | 7 | 9 |
32
Merge Sort
The second smallest item must be either the smallest item in the left sublist or the second smallest one in the right sublist (since -6 was already used).
-2
-6 | | | | | | | |
-2 | 0 | 5 | 10 |
-6 | 4 | 7 | 9 |
33
Merge Sort
0
4
5
7
9
10
-6 | -2 | | | | | | |
-2 | 0 | 5 | 10 |
-6 | 4 | 7 | 9 |
Now, both sublists are all used!
34
Merge Sort: Time Complexity
0
4
5
7
9
10
-6 | -2 | | | | | | |
-2 | 0 | 5 | 10 |
-6 | 4 | 7 | 9 |
35
Merge Sort: Time Complexity
O(log N)
-6 | -2 | 0 | 4 | 6 | 7 | 9 | 10 |
-2 | 0 | 5 | 10 |
-6 | 4 | 7 | 9 |
-2 | 5 |
0 | 10 |
-6 | 7 |
4 | 9 |
5 |
-2 |
0 |
10 |
-6 |
7 |
4 |
9 |
O(N log N)
36
Merge Sort: Implementation
def merge_sort(list):
if len(list) > 1:
mid = len(list) // 2 # round down
left = list[:mid]
right = list[mid:]
merge_sort(left)
merge_sort(right)
# TODO(students): merge left & right in the list
“else” for this is the base case, where the recursive calls are done.
We skip it here, since there’s no action item in the base case.
37
Merge Sort vs. Insertion Sort
N
N
Time (sec)
38
Can we do better?
What is the best possible time complexity for sorting problem?
Then, can we sort in O(N)?
O(N), because we need O(N) to read the input list anyway.
Yes, if we have some additional conditions.
(It was proved that O(N log N) is the best for comparison-based sorting algorithms.)
39
Linear-Time Sorting: O(n)
40
Counting Sort
41
Counting Sort
Stable sort: the original order is preserved for items with the same key.
5
7
2
5
1
5
7
[0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] |
7
5
1
5
5
7
2
1 | 2 | 5 | 5 | 5 | 7 | 7 |
42
Counting Sort
7 | 5 | 1 | 5 | 2 | 7 | 5 |
[0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] |
0 | 1 | 1 | 0 | 0 | 3 | 0 | 2 |
[0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] |
0 | 1 | 2 | 2 | 2 | 5 | 5 | 7 |
0:0 | 0:1 | 1:2 | 2:2 | 2:2 | 2:5 | 5:5 | 5:7 |
43
Counting Sort
Why backward?
→ For stable sort!
7 | 5 | 1 | 5 | 2 | 7 | 5 |
[0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] |
0 | 1 | 2 | 2 | 2 | 5 | 5 | 7 |
| 0:1 | 1:2 | 2:2 | 2:2 | 2:5 | 5:5 | 5:7 |
[0] | [1] | [2] | [3] | [4] | [5] | [6] |
| | | | | | |
4
5
6
7
1
2
3
5
44
Counting Sort: Implementation
def counting_sort(list):
output = [0] * (len(list))
count = [0] * (max(list) + 1)
� for i in range(len(list)):
count[list[i]] += 1
� for i in range(1, len(count)):
count[i] += count[i-1]
� for i in range(len(list)):
j = len(list) - 1 - i
count[list[j]] -= 1
index = count[list[j]]
output[index] = list[j]
return output
Count occurrences of each key.
Cumulative sum
Locate each element at the right position in the output.
Time complexity?
O(N)
O(k)
O(N)
Overall, O(N + k).
If k ≤ N, counting sort runs in linear time on the input size (N).
45
Sorting in Reality
46
Homework 1
def selection_sort(list):
for i in range(len(list)):
smallest = i
for j in range(i+1, len(list)):
if list[j] < list[smallest]:
smallest = j
list[i], list[smallest] = list[smallest], list[i]
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Value | -7 | -4 | -1 | 6 | 10 | 5 | 4 | 2 | 15 | 21 |
Sorted
i
smallest
swap
Q. Can you implement this with selection sort with recursion?
47
Homework 2
def merge_sort(list):
if len(list) > 1:
mid = len(list) // 2
left = list[:mid]
right = list[mid:]
merge_sort(left)
merge_sort(right)
# TODO(students): merge left & right in the list
“else” for this is the base case, where the recursive calls are done.
We skip it here, since there’s no action item in the base case.
Q. Please implement merge sort. (# TODO section below)
48
Homework 3
49
Homework 4
50
Homework 5
51