CS 161 - Section 3
CA : [Name of CA]
Section 3 agenda
Sorting and Selecting
Main idea: Divide and Conquer
Big problem
Smaller problem
Smaller problem
Yet smaller problem
Yet smaller problem
Yet smaller problem
Yet smaller problem
SELECT
5
Base Case: If the len(A) = O(1), then any sorting algorithm runs in time O(1).
Case 1: We got lucky and found exactly the k’th smallest value!
Case 2: The k’th smallest value is in the first part of the list
Case 3: The k’th smallest value is in the second part of the list
Partitioning
6
9
8
3
6
1
4
2
pivot
L = array with things smaller than A[pivot]
R = array with things larger than A[pivot]
Say we want to find SELECT(A, k)
Partitioning like this takes time O(n) since we don’t care about sorting each half.
Choosing the pivot
7
5
9
1
3
4
1
8
9
3
15
12
2
1
5
20
15
13
2
4
6
12
1
15
22
3
This takes time O(1), for each group, since each group has size 5. So that’s O(m)=O(n) total in the for loop.
8
4
5
6
12
Pivot is SELECT( , 3 ) = 6:
8
4
5
6
12
5
9
1
3
4
1
8
9
3
15
12
2
1
5
20
15
13
2
4
6
12
1
15
22
3
5
9
1
3
4
1
8
9
3
15
12
2
1
5
20
15
13
2
4
6
12
1
15
22
3
PARTITION around that 6:
This part is L
This part is R: it’s almost the same size as L.
getPivot(A):
SELECT
8
Base Case: If the len(A) = O(1), then any sorting algorithm runs in time O(1).
Case 1: We got lucky and found exactly the k’th smallest value!
Case 2: The k’th smallest value is in the first part of the list
Case 3: The k’th smallest value is in the second part of the list
Quick Sort
QuickSort
10
https://www.youtube.com/watch?v=ywWBy6J5gz8&ab_channel=AlgoRythmics
In-Place [O(1) memory!] Quick Sort
A better way to do Partition
12
8
7
1
3
5
6
4
8
7
1
3
5
6
4
1
7
8
3
5
6
4
1
3
8
7
5
6
4
1
3
8
7
5
6
4
1
3
4
7
5
6
8
Pivot
Swap!
Initialize and
Step forward.
When sees something smaller than the pivot, swap the things ahead of the bars and increment both bars.
Repeat till the end, then put the pivot in the right place.
Choose it randomly, then swap it with the last one, so it’s at the end.
Quick Sort vs Merge Sort
13
| QuickSort (random pivot) | MergeSort (deterministic) |
Running time |
|
|
In-Place? (With O(log(n)) extra memory) | Yes, can be implemented in-place (relatively) easily | Not as easily since you’d have to sacrifice stability and runtime, but it can be done |
Stable? | No | Yes |
stable sorting algorithms sort identical elements in the same order as they appear in the input
Which one would you use for a small array?
Which one would you use for an array with millions of elements?
Which one would you use for an array of unknown size?
Quick Sort vs Merge Sort
Given the small size it mostly does not matter. You could still argue for Quick sort as the expected runtime is O(n logn) but we can get away with faster than that, and even if we miss, the worst case is O(n^2). But at this scale the difference will be in the order of ms
Because for large n the Law of Large Numbers kicks in, we can reasonably expect both algorithms to run in O(n logn). It then becomes a priority choice between stability and memory-space
This might be a little of a personal choice, but usually for unknown inputs (assuming you don’t even know the expected range of sizes) we value the predictability and consistency of a deterministic algorithm, so Merge sort would be preferred. Randomized algorithms can be quite challenging to debug.
Expected Runtime
Worst-case runtime
Runtime for Randomized Algorithms
Thank You!