CSE 332 Section 5�Sorting
Announcements
Amazing no clue Awful
Properties: How to choose a sorting method?
Comparison-based / non-comparison-based: <, >, =
Stable: preserve original order of elements if equal
In-place: no need for extra data structure to store values
Online: begin with an incomplete list
Adaptive: better running time for nearly sorted input
Worst-Case Running Time
Problem 0
0. Winner of Sorts
1. A total of 206 different nations have participated across 30 summer Olympics. The most gold medals ever won by a country in a single Olympics was U.S., which won 83 gold medals in 1984. Which algorithm should we use to sort all 6,000 country-year pairs by the number of gold medals won by that country in that year?
Properties: In Place, Stable, Adaptive, Online, Non-Comparison-Based
Algorithms: Quick Sort, Insertion Sort, Radix Sort
We can make additional assumptions about the country-year pairs beyond just the ability to compare # of gold medals, since we know that out of all the country-year pairs, the maximum number of gold medals is 83. Non comparison based lets us use “linear time” sorting algorithms: specifically, Radix sort.
0. Winner of Sorts
2. Suppose we had a list of all runners already sorted by their finish time in the 100 meter dash. A small number of runners incurred time penalties, so we need to sort the list again to adjust for those penalties. What algorithm should we use for this second sort?
Properties: In Place, Stable, Adaptive, Online, Non-Comparison-Based
Algorithms: Insertion Sort, Merge Sort, Radix Sort
We have a list of all runners that is already sorted. Since it’s already sorted, we want our algorithm to be adaptive, since adaptive algorithms have better running time for nearly/already sorted input. Specifically we want to use insertion sort, since it has the best best-case runtime.
0. Winner of Sorts
3. Suppose our list of nations is already sorted by the total number of silver medals won across the 30 summer Olympics. Which algorithm should we use to sort the nations by the total number of gold medals won, while ensuring that nations with the same number of gold medals are sorted based on their number of silver medals?
Properties: In Place, Stable, Adaptive, Online, Non-Comparison-Based
Algorithms: Merge Sort, Insertion Sort, Quick Sort
We have a list of nations that has existing ordering based on the number of silver medals won for each nation. To preserve this original silver-medal based ordering, our algorithm must be stable. So, we want to use merge sort since it has a better worst-case runtime than insertion sort (n log n vs. n^2).
Comparison-based Sorting Review
Insertion Sort
Insertion sort builds a sorted subarray at the front of the original array. Takes the first element of the unsorted subarray and inserts it into the sorted subarray.
Properties:
Heap Sort
Heap sort builds a max heap, extracting the largest one-by-one to fill the sorted list (sharing the same array as the heap) from end to beginning.
Properties:
Merge Sort
Merge sort uses divide and conquer. It recursively splits an array into two halves, sorts them, and then merges them back together in sorted order.
Properties:
mergeSort(input) -> sorted input:
1. sortedLeft = mergeSort(left half of input)
2. sortedRight = mergeSort(right half of input)
3. return (merged ‘sortedLeft’ and ‘sortedRight’)
Quick Sort
Quick sort recursively partitions an array based on a pivot element, recursively sorts the subarrays on either side of the pivot, and combines the results to obtain a sorted array.
Properties:
quickSort(input) -> void:
1. pick pivot
2. partition input into ‘lessThanPivot’ and
‘greaterThanPivot’ parts
3. quickSort(lessThanPivot)
4. quickSort(greaterThanPivot)
Problem 1
Suppose we sort an array of numbers, but it turns out every element of the array is the same (e.g. [17, 17, 17, …, 17]).
What is the asymptotic runtime of the following sorting algorithms?
Sorting Algorithm | Asymptotic Runtime | Explanation |
Insertion Sort | | |
Merge Sort | | |
Quick Sort | | |
Sorting Algorithm | Asymptotic Runtime | Explanation |
Insertion Sort | O(n) | Insertion Sort will traverse the array, but since it is already ‘sorted’, no extra computation is necessary. |
Merge Sort | O(n log n) | Merge Sort always has O(n log n) runtime. You can prove this using recurrences! |
Quick Sort | O(n²) | This is the worst case for Quick Sort. Since all the elements are the same, all items will end up on the same side of each partition.(“extremely unbalanced”) |
Problem 2
2. Another Sort of Sorting…
Given an array of integers as such: {11, 13, 55, 67, 79, 10, 8, 6, 4, 2}. Please answer the following questions (assume all sorts to be done in ascending order):
What is the asymptotic runtime of the following sorting algorithms?
Here, assume we choose the leftmost element as the pivot each time for QS.
Sorting Algorithm | Asymptotic Runtime | Explanation |
Insertion Sort | | |
Merge Sort | | |
Quick Sort | | |
2. Another Sort of Sorting…
Given an array of integers as such: {11, 13, 55, 67, 79, 10, 8, 6, 4, 2}.
Please answer the following questions (assume all sorts to be done in
ascending order):
What is the asymptotic runtime of the following sorting algorithms?
Here, assume we choose the leftmost element as the pivot each time for QS.
Sorting Algorithm | Asymptotic Runtime | Explanation |
Insertion Sort | O(n²) | The array is not already sorted. At least half of the elements need to iterate through half of the array. So this is the worst case runtime. |
Merge Sort | O(n log n) | Always has O(n log n) runtime. |
Quick Sort | O(n²) | After finishing the sorting of the first pivot (11), we end up sorting the left subarray in worst-case runtime. |
Problem 3
3. Break it up and Sort it out
Suppose we have an array of size n divided into n/k subarrays of size k. The elements within each subarray are unsorted, but the subarrays themselves are ordered correctly.
What would be the worst-case runtime of:
3. Break it up and Sort it out
Suppose we have an array of size n divided into n/k subarrays of size k. The elements within each subarray are unsorted, but the subarrays themselves are ordered correctly.
What would be the worst-case runtime of:
Each element is compared at most k times, and there are n elements
O(nk)
Merge sort doesn’t care that the subarrays are sorted! If we think of the tree method, there will still be log(n) levels and O(n) work per level.
O(nlog(n))
Sorting one subarray with merge sort takes klog(k). There are n/k subarrays, so total runtime would be nlog(k).
O(nlog(k))
Non-Comparison Sorting Review
Bucket Sort
Distributes elements into their corresponding buckets. Buckets have an inherent ordering and are merged together in this ordering to produce the sorted array.
Properties:
bucketSort(input) -> sorted input:
1. create array of size B
2. put each element into their corresponding bucket
3. generate sorted array by iterating through the
buckets in order
Original Input:�[51, 11, 31, 41, 32, 2, 12, 13, 52, 42, 53]
Final output:
[11, 12, 13, 2, 31, 32, 41, 42, 51, 52, 53]
Bucket Array | |
1 | 11, 12, 13 |
2 | 2 |
3 | 31, 32 |
4 | 41, 42 |
5 | 51, 52, 53 |
B: 5
Radix Sort - 1’s Digit
Radix Sort repeatedly runs bucket sort on the elements for each significant digit, from least significant to most significant.
Original input: [478, 537, 9, 721, 3, 38, 143, 67], b: 10
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| | | | | | | | | |
Bucket Sort on 1’s Digit
| 721 | | 3, 143 | | | | 537, 67 | 478, 38 | 9 |
radixSort(input) -> sorted input:
1. create array of size b
2. for each significant digit:
3. run bucket sort on the elements using their
corresponding significant digit values
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| | | | | | | | | |
Bucket Sort on 10’s Digit
721 |
3 |
143 |
537 |
67 |
478 |
537, 38 |
3, 9 |
Radix Sort - 10’s Digit
Radix Sort repeatedly runs bucket sort on the elements for each significant digit, from least significant to most significant.
Original input: [478, 537, 9, 721, 3, 38, 143, 67], b: 10
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| | | | | | | | | |
Bucket Sort on 10’s Digit
721 |
3 |
143 |
537 |
537, 38 |
3, 9 |
radixSort(input) -> sorted input:
1. create array of size b
2. for each significant digit:
3. run bucket sort on the elements using their
corresponding significant digit values
67 |
478 |
Radix Sort - 100’s Digit
Radix Sort repeatedly runs bucket sort on the elements for each significant digit, from least significant to most significant.
Original input: [478, 537, 9, 721, 3, 38, 143, 67], b: 10
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| | | | | | 67 | 478 | | |
Bucket Sort on 10’s Digit
721 |
3 |
143 |
537 |
537, 38 |
3, 9 |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| | | | | | | | | |
Bucket Sort on 100’s Digit
3 |
3, 9 |
721 |
537 |
3, 9, 38 |
143 |
3, 9, 38, 67 |
478 |
Radix Sort - Final Output
Radix Sort repeatedly runs bucket sort on the elements for each significant digit, from least significant to most significant.
Original input: [478, 537, 9, 721, 3, 38, 143, 67], b: 10
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| | 38 | 67 | | 478 | 537 | |
Final output array:
3 |
3 |
721 |
9 |
143 |
Problem 4
4. Radix Sort (a)
Original Input: [170, 45, 75, 90, 802, 24, 2, 66]
Bucket Sort on 1’s Digit
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| | | | | | | | | |
Bucket Sort on 1’s Digit
802, 2 |
3 |
24 |
537 |
|
170, 90 |
radixSort(input) -> sorted input:
1. create array of size b
2. for each significant digit:
3. run bucket sort on the elements using their
corresponding significant digit values
66 |
|
45, 75 |
4. Radix Sort (b)
Original Input: [170, 45, 75, 90, 802, 24, 2, 66]
Bucket Sort on 10’s Digit
Bucket Sort on 1’s Digit
radixSort(input) -> sorted input:
1. create array of size b
2. for each significant digit:
3. run bucket sort on the elements using their
corresponding significant digit values
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| | | | | | | | | |
Bucket Sort on 10’s Digit
24 |
3 |
45 |
537 |
66 |
170, 75 |
|
802, 2 |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| | | | | 45, 75 | | | | |
802, 2 |
3 |
24 |
537 |
|
170, 90 |
66 |
|
90 |
4. Radix Sort (c)
Original Input: [170, 45, 75, 90, 802, 24, 2, 66]
Bucket Sort on 100’s Digit
Bucket Sort on 10’s Digit
radixSort(input) -> sorted input:
1. create array of size b
2. for each significant digit:
3. run bucket sort on the elements using their
corresponding significant digit values
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 170 | | | | | | | 802 | |
Bucket Sort on 100’s Digit
3 |
2, 24, 45, 66, 75, 90 |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| | | | | | | | | 90 |
24 |
3 |
45 |
537 |
66 |
170, 75 |
|
802, 2 |
Internal ordering from prior bucket sorts on previous digit values!
4. Radix Sort (d) Final Output!
Original Input: [170, 45, 75, 90, 802, 24, 2, 66]
Empty buckets into output array
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 170 | | | | | | | 802 | |
Bucket Sort on 100’s Digit
3 |
2, 24, 45, 66, 75, 90 |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 24 | 45 | 66 | 75 | 90 | 170 | 802 |
Output Array
3 |
2 |
Decision Tree
Decision Tree: Quick Introduction
Decision Tree Example
a<b<c; a<c<b; b<a<c; b<c<a; c<b<a; c<a<b
a<b<c; a<c<b; c<a<b
b<a<c; b<c<a; c<b<a
Ask: is a < b?
a<b<c
a<c<b; c<a<b
b<a<c
b<c<a; c<b<a
a<c<b
c<a<b
b<c<a
c<b<a
Ask: is b<c?
Ask: is a<c?
Ask: is a<c?
Ask: is b<c?
yes
no
yes
no
yes
no
yes
no
yes
no
Decision Tree Example
Thank You!