Unformatted text preview:

Algorithmic analysisSlide 2Slide 31Algorithmic analysisIntroduction. This handout tells you what you are responsible for concerning the analysis of algorithmsYou are responsible for:Weiss, chapter 5, as follows:•5.1 What is algorithmic analysis?•5.2 Examples of running time•5.3 NO, not responsible for this No.•5.4 Definition of Big-oh and Big-theta. You should be able to use these definitions.•5.5 Everything except harmonic numbers. This includes the repeated doubling and repeated having stuff.•5.6. No, not responsible for this section. NO. Instead, you should know the following algorithms as presented in the handout on correctness of algorithms and be able to determine their order of execution time: linear search, binary search, partition, insertion sort, and selection sort •5.7 Checking an algorithm analysis•5.8 Limitations of big-oh analysis•The material presented in this handout (you should be able to perform the analysis of the mergesort execution time and know how to fix Quicksort).Order of execution time of mergesort// sort b[h..k]public static void mergesort(int[] b, int h, int k) {if (k+1-h <= 1)return;int e= (h+k+1)/2;mergesort(b, h, e-1);mergesort(b, e, k);merge(b, h, e, k);}We know that merge takes time proportional to the number of elements in b[h..k], i.e. it is an O(k+1-h) algorithm. Suppose it takes s*(k+1-h) steps. Based on this assumption, we figure out the order of execution of mergesort.Define T(n) to be the number of steps it takes to mergessort an array of size n.We have:20: T(1) = 1 (assume 1 unit of time for executing the base case) 21: T(2)= <look at the function body> 2*T(1) + 2s= <use T(1)> 2*1 + 2s Note that 2 = 21 *122: T(4)= <look at the function body> 2*T(2) + 4s= <use T(2)> 2*(2+2s) + 4s= <arithmetic> 4 + 8s Note that 8 = 22 *223: T(8)= <look at the function body> 2*T(4) + 8s= <use T(4)> 2*(4+8s) + 8s= <arithmetic> 8 + 24s Note that 16 = 23 *3We see a pattern here: T(2p) = 2p + 2p *p*sor: T(n) = n + n*log(n)*sAnd indeed, we can prove this formula using INDUCTION. Proving a theorem by induction is akin to understanding a recursive function. We prove the theorem for a base case. Then, we prove it for the recursive (inductive) case under the assumption that it holds for smaller cases.Theorem: T(2p) = 2p + 2p *p*sProof of base case: T(20) = T(1) = 1 (earlier analysis)Proof of recursive case: Assume p>0. We prove the theorem under the assumption thatT(2k) = 2k + 2k *k*sholds for 0<=k<p:2T(2p)= <look at the function body> 2*T(2p-1) + 2p s= <use assumption, with k=p-1> 2*(2p-1 + 2p-1 *(p-1)*s) + 2p s= <arithmetic> 2p + 2p *(p-1)*s + 2p s= <arithmetic> 2p + 2p *p*sIsn’t that simple?From the theorem, we see that mergesort takes time O(n log n) to sort an array of size n.Discovering the theorem. Take a look at how we discovered the theorem. We calculated T(1), T(2), T(4), T(8), etc. until we saw a pattern. Then, we just formulated the theorem as that pattern.A more general theoremWe have proved that mergesort takes time O(n log n) to sort an array of size n, when n is a power of 2. It is easy to show that it then takes O(n log n) time for an array of any size.But we can do more. The analysis that we did holds whenever the recursive method satisfies certain assumptions, which we describe in this theorem:Theorem: Suppose a recursive method that processes an array takes 1 step for an array of size 0 or 1 and, for an array of size n>1 does two things (in any order):• Performs O(n) steps, processing the array.• Recursively calls itself twice to process the first half and the last half of the array, of the same size.Then the algorithm takes time O(n log n) to process an array of size n.Let’s look at quicksort. In the best case, each call on partition partitions the array into two equal halves --at least, each contains no more than 1/2 of the array. Quicksort then partitions these two halves. Further, method partition takes time proportional to the size of the array segment that it is partitioning. Therefore, in the best case, quicksort takes time O(n log n) to sort an array of size n.It has been shown that the expected or average case time for quicksort is also O(n log n), but the analysis is beyond the scope of CS211.In the worst case, quicksort is O(n2).3// Sort b[h..k]public static void quicksort (int[] b, int h, int k) {// inv: the segment to be sorted is in ascending order// if and only if b[h..k] is in ascending order// bound function: size of segment b[h..k]while (true) {if (k+1-h <= 10) {insertionSort(b,h,k);return; }medianOf3(b,h,k);// {b[h] is between b[(j+k/2)] and b[k]}int j= partition(b,h,k);// {b[h..j-1] <= b[j] <= b[j+1..k]}if (j-h <= k-j) {quicksort(b,h,j-1); // sort the smaller segment// {original segment is sorted if b[j+1..k] is}h= j+1;}else {quicksort(b,j+1,k); // sort the smaller segment// {original segment is sorted if b[h..j-1] is}k= j-1;}}}// Permute b[h], b[k], and b[(h+k)/2 to store their// median in b[h]public static void medianOf3(int b, int h, int k)Fixing Quicksort so that it takes at most O(n) space to sort an array of size n and so that it is more efficient. Here’s the original quicksort:// sort b[h..k]public static void quicksort(int b, int h, int k) {if (k+1-h <= 1){ return; }int j= partition(b,h.k);// {b[h..j-1] <= b[j] <= b[j+1..k]}quicksort(b,h,j-1);quicksort(b,j+1,k);}It has problems.1. The pivot value b[h] may be the smallest element of the array, and if so, partition creates one segment, b[h..j-1], that is empty and one segment, b[j+1..k] that contains all but one element. If this happened at each iteration, the depth of recursion would be k-h, so O(k-h), that is, linear space and would take O(k-h)2) time.We can’t solve this problem completely. But we can help it a bit by making b[h] be the median of three of the array values before doing the partition. This give more chance that partition will produce segments of nearly equal size.2. Quicksort is particularly inefficient on small arrays, because of all the method calls. By experiment, it has been determined that insertion sort does better on arrays of about 10 or fewer elements.So, we change the base case from an array of size 1 or less to an array of size 10 or less and use insertion sort to sort it.3. We have not solved the problem that in some cases the depth of recursion will be linear in the size of


View Full Document

CORNELL CS 211 - Study Notes

Documents in this Course
B-Trees

B-Trees

10 pages

Hashing

Hashing

3 pages

Load more
Download Study Notes
Our administrator received your request to download this document. We will send you the file to your email shortly.
Loading Unlocking...
Login

Join to view Study Notes and access 3M+ class-specific study document.

or
We will never post anything without your permission.
Don't have an account?
Sign Up

Join to view Study Notes 2 2 and access 3M+ class-specific study document.

or

By creating an account you agree to our Privacy Policy and Terms Of Use

Already a member?