Goal of Sorting
• Remove the most inversions with the least
number of operations (comparisons / swaps)
Inversions
• How many places off an element is in an array • Sorting is just removing all inversions from a list • Can count inversions one element at a time
Counting Inversions
• Unsorted List = 5 1 2 6 8 3 9 4 7
• Start at ‘5’
– Is 5 > 1? Yes
– Is 5 > 2? Yes
– Is 5 > 6? No
– Is 5 > 8? No
– Is 5 > 3? Yes
– Is 5 > 9? No
– Is 5 > 4? Yes
– Is 5 > 7? No
• Whenever an element is greater than an element after it
Counting Inversions
• Unsorted List = 5 1 2 6 8 3 9 4 7
• Continue counting inversions for each of the following
elements
• Sum up the number of inversions for each element
Counting Inversions
Unsorted List = 5 1 2 6 8 3 9 4 7
5 Inversions 1 Inversions
5>1 1 x
5>2 1 1>2 0
5>6 0 1>6 0
5>8 0 1>8 0
5>3 1 1>3 0
5>9 0 1>9 0
5>4 1 1>4 0
5>7 0 1>7 0
Counting Inversions
Unsorted List = 5 1 2 6 8 3 9 4 7
2 Inversions 6 Inversion
x x
x x
2>6 0 x
2>8 0 6>8 0
2>3 0 6>3 1
Counting Inversions
Unsorted List = 5 1 2 6 8 3 9 4 7
8 Inversions 3 Inversions
x x
x x
x x
x x
8>3 1 x
8>9 0 3>9 0
8>4 1 3>4 0
8>7 1 3>7 0
Counting Inversions
Unsorted List = 5 1 2 6 8 3 9 4 7
9 Inversion 4 Inversions
x x
x x
x x
x x
x x
x x
Counting Inversions
Unsorted List = 5 1 2 6 8 3 9 4 7
• Total Inversions = sum of all individual element inversions
Inversion Questions
• What is the greatest number of inversions a list can have?
• What is the average number of inversions a list can have?
• How many inversions can be removed in one operation
Sorting Analysis
• Selection Sort
Selection Sort
• Brief reminder of selection sort
• What is the worst case complexity of selection
sort? (O)
• What is the average case complexity of
selection sort (Θ)
• What is the best case complexity of selection
Selection Sort (Worst Case)
• for(int i=0; i<unsortedArray.length-1; i++)
– for(int j=i+1; j<unsortedArray.length; j++) • Basic operation
• In the worst case how many times will the
basic operation execute?
Selection Sort (Worst Case)
• Outer loop – executes n-1 times
• Inner loop - executes for each outer loop
• Inner loop
– i=0 – n-1 times – i=1 – n-2 times – i=2 – n-3 times – …
Selection Sort (Worst Case)
• Inner loop
– Average of (n-1) + (n-2) + …n-(n-1) – Average = n/2 times
– Ex: n=5
• J=1 4 operations
• J=2 3 operations • J=3 2 operations
Selection Sort (Worst Case)
• Outer loop = (n-1)
– Inner loop = n/2
• Multiply outer * inner
• (n-1) * (n/2)
• (n*n – n) / 2
Selection Sort (Average Case)
• Do list permutations matter?
• Will the algorithm use a different number of
comparisons based on the order of the list?
• for(int i=0; i<unsortedArray.length-1; i++)
– for(int j=i+1; j<unsortedArray.length; j++) • Basic operation
• No
Selection Sort (Best Case)
Insertion Sort
• Brief reminder of insertion sort
• What is the worst case complexity of Insertion
sort? (O)
• What is the average case complexity of
Insertion sort? (Θ)
• What is the best case complexity of Insertion
Insertion Sort (Worst Case)
• for(int i=1; i<unsortedArray.length; i++)
– for(int j=i-1; j>=0 && !done; j--) • Basic operation
• if(unsortedArray[i] > unsortedArray[j]) – done = true;
• In the worst case how many times will the
basic operation execute?
Insertion Sort (Worst Case)
• Outer loop – executes n-1 times
• Inner loop - executes for each outer loop until
the correct position is found
• Inner loop
– Assume worst case
– Assume loop will never finish early
– Inner loop will execute a varying number of times • Same as selection sort
Insertion Sort (Worst Case)
• Outer loop = (n-1)
– Inner loop = n/2
• Multiply outer * inner
• (n-1) * (n/2)
• (n*n – n) / 2
Insertion Sort (Average Case)
• Do list permutations matter?
• for(int i=1; i<unsortedArray.length; i++)
– for(int j=i-1; j>=0 && !done; j--) • Basic operation
• if(unsortedArray[i] > unsortedArray[j]) – done = true;
• Yes – may only have to do one comparison in
Insertion Sort (Average Case)
• Assume all list permutations are equally likely
• The inner loop worst case = all comparisons
– Average of all times run = n/2
• The inner loop best case = one comparison
• What is the average number of times?
• On average the inner loops will only run half
of the worst case time
Insertion Sort (Average Case)
• Outer loop = (n-1)
– Inner loop = n/4
• Multiply outer * inner
• (n-1) * (n/4)
• (n*n – n) / 4
Insertion Sort (Best Case)
• As mentioned in the average case
• Least number of inner loop comparisons = 1
• Outer loop = n-1
• Inner loop = 1
Quicksort
• Brief reminder of Quicksort
• What is the worst case complexity of
Quicksort? (O)
• What is the average case complexity of
Quicksort? (Θ)
• What is the best case complexity of Quicksort?
Analysis of quicksort
• Assume all input elements are distinct.
• In practice, there are better
partitioning algorithms for when duplicate input elements may exist.
• Let T(n) = worst-case running time on
Worst-case of quicksort
• Input sorted or reverse sorted.
• Partition around min or max element.
• One side of partition always has no elements.
Worst-case recursion tree
Worst-case recursion tree
cn
T(0) T(n–1)
Worst-case recursion tree
cn
T(0) c(n–1)
Worst-case recursion tree
T(n) = T(0) + T(n–1) + cn
cn
T(0) c(n–1)
Worst-case recursion tree
T(n) = T(0) + T(n–1) + cn
T(0) c(n–2)
T(0)
(1)
cn
T(0) c(n–1)
Worst-case recursion tree
T(n) = T(0) + T(n–1) + cn
T(0) c(n–2)
T(0)
(1)
cn
(1) c(n–1)
Worst-case recursion tree
T(n) = T(0) + T(n–1) + cn
(1) c(n–2)
(1)
(1)
T(n) = (n) + (n2)
= (n2)
h = n
Best-case analysis
If we’re lucky, PARTITION splits the array evenly:
T(n) = 2T(n/2) + (n) = (n lg n)
What if the split is always 101 :109 ?
( ))
( 109
10
1 n T n n
T n
Analysis of “almost-worst” case
Analysis of “almost-worst” case
cn
nT 101 T
n 10Analysis of “almost-worst” case
cn cn 10 1 cn 10 9
nT 1001 T
n 1009 T
n 1009 T
n 100Analysis of “almost-worst” case
(1)
(1)
… …
log10/9n
…
O(n) leaves
O(n) leaves
log10n
Analysis of “almost-worst” case
(1)
(1)
… …
log10/9n
T(n) £ cn log n + O(n)
…
cn log n £
O(n) leaves
O(n) leaves
(n lg n)
Quicksort (Average Case)
• nlog(n)
• Not going to prove this rigorously
• Think of the good and bad splits in the recursion tree
– Even a bad split gives the best case
– Always having the worst split gives the worst case – On average the splits will be better than the
Merge Sort
• Brief reminder of Merge Sort
• What is the worst case complexity of Merge
Sort? (O)
• What is the average case complexity of Merge
Sort? (Θ)
• What is the best case complexity of Merge
Merge Sort (Worst Case)
• Always breaks the lists up into two equal
(possibly 1-off) sub lists
• This creates a balanced binary recursion tree
• Height of tree = log(n)
• Work done merging = size of list
Merge Sort (Worst Case)
• T(n) =
– (# of sub problems) * (size of sub problems) – + work done dividing and merging
• T(n) = 2(n/2) + n
– Technically T(n) = T(ceiling(n/2)) + T(floor(n/2)) + (n – 1)
Merge Sort (Worst Case)
• T(n) = 2T(n/2) + n • F(n) = n
• Logba = log
22 = 1
• Compare n to n
• f(n) = n(logba)
– n = n
• Case 2 T(n) = Θ(n^(logba) * log(n))
• T(n) = Θ(nlog(n))
Merge Sort (Average Case)
• No different than the worst case
• Algorithm is the same regardless of the input
Merge Sort (Best Case)
• No different than the worst case
• Algorithm is the same regardless of the input
Decision Tree
• Represent Comparisons as a decision tree
• Each node represents a comparison
• Each number represents an element number
• All leaves represent all possible list
permutations
Decision Tree
List of Size 3
Decision Tree
List of Size 3
0:1
0:2 0:2
Decision Tree
List of Size 3
0:1
0:2 0:2
element[0] <= element[1] element[0] > element[1]
1:2 1:2
e[0] <= e[2] e[0] > e[2] e[0] <= e[2] e[0] > e[2]
Decision Tree
List of Size 3
0:1
0:2 0:2
element[0] <= element[1] element[0] > element[1]
1:2 1:2
e[0] <= e[2]
e[0] > e[2] e[0] <= e[2] e[0] > e[2]
e[2] < e[0] <= e[1] e[1] < e[0] <= e[2]
e[0] <= e[2] <=
e[1] e[0] <= e[2] < e[1] e[1] <= e[2] <= e[0] e[2] < e[1] < e[0]
e[1] <=
e[2] e[1] > e[2] e[1] <= e[2]
Decision Tree - Example
List of Size 3
0:1
0:2 0:2
element[0] <= element[1] element[0] > element[1]
1:2 1:2
e[0] <= e[2]
e[0] > e[2] e[0] <= e[2] e[0] > e[2]
e[2] < e[0] <= e[1] e[1] < e[0] <= e[2]
e[0] <= e[2] <=
e[1] e[0] <= e[2] < e[1] e[1] <= e[2] <= e[0] e[2] < e[1] < e[0]
e[1] <=
e[2] e[1] > e[2] e[1] <= e[2]
Decision Tree - Example
List of Size 3
0:1
0:2 0:2
element[0] <= element[1] element[0] > element[1]
1:2 1:2
e[0] <= e[2]
e[0] > e[2] e[0] <= e[2] e[0] > e[2]
e[2] < e[0] <= e[1] e[1] < e[0] <= e[2]
e[0] <= e[2] <=
e[1] e[0] <= e[2] < e[1] e[1] <= e[2] <= e[0] e[2] < e[1] < e[0]
e[1] <=
e[2] e[1] > e[2] e[1] <= e[2]
Decision Tree - Example
List of Size 3
0:1
0:2 0:2
element[0] <= element[1] element[0] > element[1]
1:2 1:2
e[0] <= e[2]
e[0] > e[2] e[0] <= e[2] e[0] > e[2]
e[2] < e[0] <= e[1] e[1] < e[0] <= e[2]
e[0] <= e[2] <=
e[1] e[0] <= e[2] < e[1] e[1] <= e[2] <= e[0] e[2] < e[1] < e[0]
e[1] <=
e[2] e[1] > e[2] e[1] <= e[2]
e[1] > e[2]
Decision Tree - Example
List of Size 3
0:1
0:2 0:2
element[0] <= element[1] element[0] > element[1]
1:2 1:2
e[0] <= e[2]
e[0] > e[2] e[0] <= e[2] e[0] > e[2]
e[2] < e[0] <= e[1] e[1] < e[0] <= e[2]
e[0] <= e[2] <=
e[1] e[0] <= e[2] < e[1] e[1] <= e[2] <= e[0] e[2] < e[1] < e[0]
e[1] <=
e[2] e[1] > e[2] e[1] <= e[2]
e[1] > e[2]
Decision Tree - Example
List of Size 3
0:1
0:2 0:2
element[0] <= element[1] element[0] > element[1]
1:2 1:2
e[0] <= e[2]
e[0] > e[2] e[0] <= e[2] e[0] > e[2]
e[2] < e[0] <= e[1] e[1] < e[0] <= e[2]
e[0] <= e[2] <=
e[1] e[0] <= e[2] < e[1] e[1] <= e[2] <= e[0] e[2] < e[1] < e[0]
e[1] <=
e[2] e[1] > e[2] e[1] <= e[2]
e[1] > e[2]
6 > 2
Decision Tree - Example
List of Size 3
0:1
0:2 0:2
element[0] <= element[1] element[0] > element[1]
1:2 1:2
e[0] <= e[2]
e[0] > e[2] e[0] <= e[2] e[0] > e[2]
e[2] < e[0] <= e[1] e[1] < e[0] <= e[2]
e[0] <= e[2] <=
e[1] e[0] <= e[2] < e[1] e[1] <= e[2] <= e[0] e[2] < e[1] < e[0]
e[1] <=
e[2] e[1] > e[2] e[1] <= e[2]
e[1] > e[2]
6 > 2
Decision Tree - Example
List of Size 3
0:1
0:2 0:2
element[0] <= element[1] element[0] > element[1]
1:2 1:2
e[0] <= e[2]
e[0] > e[2] e[0] <= e[2] e[0] > e[2]
e[2] < e[0] <= e[1] e[1] < e[0] <= e[2]
e[0] <= e[2] <=
e[1] e[0] <= e[2] < e[1] e[1] <= e[2] <= e[0] e[2] < e[1] < e[0]
e[1] <=
e[2] e[1] > e[2] e[1] <= e[2]
e[1] > e[2]
6 > 2 6 > 3 2 <= 3
Proof Sorting
O
nlog(n)
• For a list of size n– n! possible combinations
• n! possible combinations
– At least n! leaves in the decision tree
• At height h a binary tree has < 2h leaves
• n! < 2h
• log(n!) < h
Counting Sort
• Lecture5_mit6046jf05_demaine_lec05_01.pdf
Counting Sort Code
Counting Sort (Worst Case)
• Must loop through the array exactly once
• Must loop through the secondary array exactly
once
• Must loop through the array again
Counting Sort (Worst Case)
• Must loop through the array exactly once
– O(n)
• Must loop through the secondary array exactly
once
– O(k), where k is the range of the values
• Must loop through the array again
– O(n)
• May have to copy the array back
Counting Sort (Worst Case)
• O(n) + O(k) + O(n) = O(2n + k) O(n)
– Although if k is large, k will dominate n • This is very possible
• If need to copy and initialize new array
• O(n) + O(n) + O(k) + O(n) + O(n)
When to Use Counting Sort
• When values are integers
• When range is known
Properties of Sorting
• Stability
– Preserved order of equal elements – Show by example
• In place
– If the sort can be done with the input array and
does not require extra space (auxiliary array)
• In place if it does not require extra space
Which sorts are in place?
• Selection sort
• Insertion sort
• Quicksort
• Merge sort
Which sorts are in place?
• Selection sort • Insertion sort
• Quicksort
– Log(n) space version exists (recursive calls) – No additional array required
– Technically not in place since it is not O(1)
• Mergesort
– In place version exists
Stability Example
• StableExample.xlxs
Importance of Stability
• Sorting by multiple columns
• Important for database queries
– ORDER BY user_id ASC, order_id ASC • Will get all users in order
• Will get all orders for each user in order
• No stability means the query will return results
out of order
Which sorts are stable?
• Selection sort
• Insertion sort
• Quicksort
• Merge sort
Which sorts are stable?
• Selection sort
• Insertion sort
• Quicksort
• Mergesort
Sorting
Algorithm Best Case
Ω Average CaseΘ Worst CaseO In-Place Stable Selection Sort n2 n2 n2 Yes No
Insertion Sort n n2 n2 Yes Yes
Quicksort nlog(n) nlog(n) n2 No No
Merge Sort nlog(n) nlog(n) nlog(n) No Yes
Counting Sort* n n n No Yes