$ \def\compare{ {\mathrm{compare}} } \def\swap{ {\mathrm{swap}} } \def\sort{ {\mathrm{sort}} } \def\insert{ {\mathrm{insert}} } \def\true{ {\mathrm{true}} } \def\false{ {\mathrm{false}} } \def\BubbleSort{ {\mathrm{BubbleSort}} } \def\SelectionSort{ {\mathrm{SelectionSort}} } \def\Merge{ {\mathrm{Merge}} } \def\MergeSort{ {\mathrm{MergeSort}} } $
Careful analysis of correctness of SelectionSort
01 SelectionSort(a):
02 n <- size(a)
03 for j = 1 to n - 1 do
04 min <- j
05 for i = j+1 to n do
06 if compare(a, min, i)
07 min <- i
08 endif
09 endfor
10 swap(a, j, min)
11 endfor
Focus on efficiency
01 SelectionSort(a):
02 n <- size(a)
03 for j = 1 to n - 1 do
04 min <- j
05 for i = j+1 to n do
06 if compare(a, min, i)
07 min <- i
08 endif
09 endfor
10 swap(a, j, min)
11 endfor
How many comparisons?
How many swaps?
How many “elementary” operations (including arithmetic)?
Uncertain Parameters:
Assume:
Focus on asymptotic growth of # of operations as function of input size
Qualitative measure of function growth:
Formally: $f$, $g$ functions, write $f = O(g)$ if
01 SelectionSort(a):
02 n <- size(a)
03 for j = 1 to n - 1 do
04 min <- j
05 for i = j+1 to n do
06 if compare(a, min, i)
07 min <- i
08 endif
09 endfor
10 swap(a, j, min)
11 endfor
Given a computational task:
How could divide the sorting task into sub-tasks?
As before, $a$ an array of size $n$
MergeSort algorithm:
# sort values of a between indices i and j-1
MergeSort(a, i, j):
if j - i = 1 then
return
endif
m <- (i + j) / 2
MergeSort(a,i,m)
MergeSort(a,m,j)
Merge(a,i,m,j)
Establish two claims:
Claim 1 (merge). If $a[i..m-1]$ and $a[m..j]$ are sorted, then after $\Merge(a, i, m, j)$, $a[i..j]$ is sorted.
Claim 2. For any indices $i < j$, after calling $\MergeSort(a, i, j)$, $a[i..j]$ is sorted.
00 # sort values of a between indices i and j-1
01 MergeSort(a, i, j):
02 if j - i = 1 then
03 return
04 endif
05 m <- (i + j) / 2
06 MergeSort(a,i,m)
07 MergeSort(a,m,j)
08 Merge(a,i,m,j)
Consider $\MergeSort(a, i, j)$, define $k = j - i$ to be size
$P(k)$: for every $k’ \leq k$, $\MergeSort(a, i, j)$ with size $k’$ succeeds
Base case $k = 1$:
Inductive step $P(k) \implies P(k+1)$:
How efficient is MergeSort?
00 # sort values of a between indices i and j-1
01 MergeSort(a, i, j):
02 if j - i = 1 then
03 return
04 endif
05 m <- (i + j) / 2
06 MergeSort(a,i,m)
07 MergeSort(a,m,j)
08 Merge(a,i,m,j)
00 # sort values of a between indices i and j-1
01 MergeSort(a, i, j):
02 if j - i = 1 then
03 return
04 endif
05 m <- (i + j) / 2
06 MergeSort(a,i,m)
07 MergeSort(a,m,j)
08 Merge(a,i,m,j)
Observation 1. Let $k = j - i$ be the size of the method call $\MergeSort(a, i, j)$. Then running time is $O(k) + $ running time of recursive calls on lines 6-7.
Observation 2. Recursive calls have size $k / 2$.
Define $\log$ by
Another way
Facts.
Running time $T(n)$ of $\MergeSort(a, 1, n+1)$:
\[\begin{align*} T(n) &= 2 T(n/2) + O(n)\\ &= 4 T(\frac n 4) + 2 O(\frac n 2) + O(n)\\ &= 8 T(\frac n 8) + 4 O(\frac n 4) + 2 O(\frac n 2) + O(n)\\ &\vdots\\ &= n T(1) + \frac n 2 O(2) + \cdots + 8 O(\frac n 8) + 4 O(\frac n 4) + 2 O(\frac n 2) + O(n)\\ &= O(n) + O(n) + \cdots + O(n) + O(n) + O(n)\\ &{}\\ &= \end{align*}\]