1 Joe Meehean
Problem arrange comparable items in list into sorted order Most sorting algorithms involve comparing item values We assume items define < operator > operator == operator
void sort( Iterator begin, Iterator end) data items must override < operator void sort( Iterator begin, Iterator end, Comparator cmp) Comparator is comparison functor cmp(a,b) returns true if a should go before b in the sorted list Often implemented using quick sort 3
Aspects we care about run time memory cost Types of algorithms comparison vs. non comparison Examples of important sorting algorithms Google Search: real world example 4
Obvious algorithms are O(N 2 ) Clever ones are O(NlogN) special purpose sorts can go even faster Additional considerations does algorithm always take worst-case time? what is the average case? what happens when the list is already sorted? 5
In-place sorts list with constant extra memory e.g., temporary variables Not in-place requires additional memory in relation to input size e.g., another parallel list
Comparison sort compare items in the list place smaller items near the front fastest worst case: O(NlogN) Non-comparison sort sort using special properties of items use/extrapolate additional information e.g., non-comparison sort O(Range+N) 7
Sorting algorithm based on heaps Idea insert items from unsorted list into heap use heap::removeMin to get items out of heap in sorted order put items back into list in sorted order 8
Problems with this approach Complexity not ideal inserting N items into heap is O(NlogN) removing N items from heap is O(NlogN) it would be better if would could do the whole thing in O(NlogN) Memory cost not in-place need original list + a heap 9
Can “heapify” a vector/array in O(N) convert unsorted vector into a max heap For each parent node (N/2 to 0) make sure its larger than its children if its not, swap parent with largest child shiftDown(int pos, K val) Minor complication vector starts at 0 not 1 like a normal heap 10
L P
P swap L
P L
L P R
L P R swap
L P R
L P R
L P R swap
L P R
L P R
L P R swap
L P R PL R swap
L P R PL R
L P R
L P R swap
L P R PL R
L P R PL R
O(N) proof is somewhat complex see Weiss if interested Intuitively it is faster because we only need to shiftdown ½ the nodes plus starting at bottom reduces number of shift downs inserting each node into a heap shifts down for each insert (all the nodes) 29
Removing an item from the heap creates a space at the end This space is where the largest item should go in the finished array Why don’t we just put it there recall in heap::removeMax we return h[first] and replace h[first] with h[last] instead lets swap h[first] with h[last] 30
= Heap= Sorted Vector swap
= Heap= Sorted Vector
L P R shift down = Heap= Sorted Vector
L P R shift down = Heap= Sorted Vector
P shift down = Heap= Sorted Vector
swap = Heap= Sorted Vector
shift down L P R = Heap= Sorted Vector
= Heap= Sorted Vector shift down L P R
= Heap= Sorted Vector
Position in the Array Item value
Heapify O(N) In-place conversion of heap into sorted array O(NlogN) O(N) + O(NlogN) = O(NlogN) Costs the same if array was sorted to begin with 41
42
Fundamental Idea if all values in sorted array A are less than all values in sorted array B we can easily combine them an array of size 1 is sorted A B A
1) if number of items in A is one or zero, return 2) Choose a value from A to be the pivot 3) Partition A into sub-lists all values ≤ pivot into left part all values ≥ pivot into the right part 4) Return quicksort(L-part) + pivot + quicksort(R-part) 44
In practice items are already in the correct place when we get to the bottom. All work is done on the way down.
Goal: Choose the median value so that left and right arrays are the same size If we choose the smallest value each partition only reduces the problem by one sorting tree height will be N instead of log N Same if we choose the largest 60
Actually finding median is O(N) Choose 1 st item very bad if A is already sorted or reverse sorted Choose a random item (index) OK if you have a fast, accurate random number generator we don’t 61
Reduces comparisons by 14% Compare the center, left, and right items choose the median as the pivot only works if >= 3 items to be sorted Partitioning optimization place smallest of 3 in left (≤ pivot) place largest of 3 in right (≥ pivot) place pivot in the center 62
63 Choose the median of 3 place in the right positions left right center
64 Choose the median of 3 place in the right positions left right center
65 Swap pivot with right − 1 left right center
66 Swap pivot with right − 1 left right center
67 Use indices hi and lo to partition remainder of the array increment lo until it finds a value ≥ pivot decrement hi until it finds a value ≤ pivot lo hi
68 When lo & hi stop swap lo and hi increment lo decrement hi lo hi
69 lo hi When lo & hi stop swap lo and hi increment lo decrement hi
70 Repeat until lo > hi lo hi
lo hi Repeat until lo > hi
lo hi Repeat until lo > hi
73 Restore the pivot swap with lo lo hi
74 Done lo hi
Position in the Array Item value
Values equal to the pivot e.g., A[lo] ≥ pivot OR A[lo] > pivot worst case entire list is the same value if we didn’t swap for duplicates, lo would be all the way at the right uneven partition best to swap values that are equal to pivot 76
Small lists insertion sort is faster for N < 20 Quick sort is recursive will always, eventually, sort lists < 20 large lists are broken down into small ones commonly quick sort is used until each sub-list is <= 10 then the sub-list is sorted using insertion sort reduces run-time by 15% 77
At each level, N comparisons to pivots Levels: worst case pivot is smallest or largest value call graph linear: N levels Levels: best-case pivot is median value call graph balanced binary tree: log 2 N levels Worst-case: O(N 2 ) Best-case: O(NlogN) No better/worse if array already sorted
Quick sort A: select 1 st item as pivot B: select random item as pivot A O(NlogN) on average O(N 2 ) if list is already mostly sorted B O(NlogN) on average O(N 2 ) if random number always select smallest 79
Algorithm A & B would be identical if all inputs are equally likely but partially sorted lists are far more likely Bad inputs A is always bad B has different run times for the same input depends on random numbers selected unlike inputs, all random numbers equally likely B more likely have average run time 80
General comparison sorts have a best- case of O(N log N) Non-comparison sorts use extra information about items can sort faster than O(N log N) bucket sort radix sort 82
Used for sorting positive integers with a small range (less than M) Algorithm for input A 1, A 2, A 3, … A N, each a positive int less than M make an array count of size M foreach input A i => count[A i ]++ scan count printing the ints we’ve seen 83
A A max =
A count
A count i
A count i
A count i
A count i
A count i
A count i
A count i
A count i
A count i j
A count i j
A count i j
A count i j
A count i j
A count i j
A i j
A i j
A i j
A i j
A i j
Not-in place requires an extra M memory Complexity scan the original list O(N) scan the “count” list O(M) O(M+N) 105
Requires items are sequences of comparables numbers (sequence of digits) strings (sequence of characters) Useful for short sequences of comparables Idea sort each position in sequence separately 106
Use an auxiliary array of queues array must be large enough to store queues for full range of digits 0-9 for numbers a-z for words Process sequences from R to L least significant “digit” first Each pass evaluates the next digit store each item in queue in auxiliary array based on value of current digit dequeue items back into original array 107
[132, 355, 104, 327, 111, 285, 391, 543, 123, 535] [ ] 108
[132, 355, 104, 327, 111, 285, 391, 543, 123, 535] 109
[132] [ ] [132, 355, 104, 327, 111, 285, 391, 543, 123, 535] 110
[132] [355] [ ] [132, 355, 104, 327, 111, 285, 391, 543, 123, 535] 111
[132] [355] [ ] [104] [ ] [132, 355, 104, 327, 111, 285, 391, 543, 123, 535] 112
[132] [355] [ ] [104] [ ] [327] [ ] [132, 355, 104, 327, 111, 285, 391, 543, 123, 535] 113
[132] [355] [111] [ ] [104] [ ] [327] [ ] [132, 355, 104, 327, 111, 285, 391, 543, 123, 535] 114
[132] [355, 285] [111] [ ] [104] [ ] [327] [ ] [132, 355, 104, 327, 111, 285, 391, 543, 123, 535] 115
[132] [355, 285] [111, 391] [ ] [104] [ ] [327] [ ] [132, 355, 104, 327, 111, 285, 391, 543, 123, 535] 116
[132] [355, 285] [111, 391] [ ] [104] [543] [327] [ ] [132, 355, 104, 327, 111, 285, 391, 543, 123, 535] 117
[132] [355, 285] [111, 391] [ ] [104] [543, 123] [327] [ ] [132, 355, 104, 327, 111, 285, 391, 543, 123, 535] 118
[132] [355, 285, 535] [111, 391] [ ] [104] [543, 123] [327] [ ] 119
[132] [355, 285, 535] [111, 391] [ ] [104] [543, 123] [327] [ ] [111, 391, 132, 543, 123, 104, 355, 285, 535, 327] 120
[ ] 121
[111, 391, 132, 543, 123, 104, 355, 285, 535, 327] [111] [123, 327] [132, 535] [543] [355] [285] [104] [391] [ ] 122
[111] [123, 327] [132, 535] [543] [355] [285] [104] [391] [ ] [104, 111, 123, 327, 132, 535, 543, 355, 285, 391] 123
[ ] 124
[104, 111, 123, 327, 132, 535, 543, 355, 285, 391] [104, 111, 123, 132] [285] [327, 355, 391] [535, 543] [ ] 125
[104, 111, 123, 132] [285] [327, 355, 391] [535, 543] [ ] [104, 111, 123, 132, 285, 327, 355, 391, 535, 543] 126
Each pass puts items in correct Q: O(N) moves items from Q to array: O(N) pass total: O(N) # of passes depends on # of digits O(N * #digits) 127
Sort every number between 0 and 4,294,967,296 (4 billion something) Merge Sort Nlog 2 N N = 4 billion Log 2 (4 billion) = 32 4 billion * 32 = 128 billion operations 128
Radix sort O(N * #digits) N = 4 billion # of digits = 10 4billion * 10 = 40 billion Radix sort about 3 times faster 129
BestWorstAvgIn-Place SelectionO(N 2 ) Yes InsertionO(N)O(N 2 ) Yes HeapO(NlogN) Yes MergeO(NlogN) No QuickO(NlogN)O(N 2 )O(NlogN)Yes BucketO(N + M) No RadixO(N * #digits) No 130
131