1 / 26

Understanding Quicksort and Mergesort Algorithms

Learn about the Quicksort and Mergesort algorithms, including their complexities, recurrence relations, and implementations. Explore the partition and merge steps with examples.

hopeg
Download Presentation

Understanding Quicksort and Mergesort Algorithms

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Sorting Algorithms2

  2. Quicksort General Quicksort Algorithm: • Select an element from the array to be the pivot • Rearrange the elements of the array into a left and right subarray • All values in the left subarray are < pivot • All values in the right subarray are > pivot • Independently sort the subarrays • No merging required, as left and right are independent problems [ Parallelism?!? ]

  3. Quicksort void quicksort(int* arrayOfInts, int first, int last) { int pivot; if (first < last) { pivot = partition(arrayOfInts, first, last); quicksort(arrayOfInts,first,pivot-1); quicksort(arrayOfInts,pivot+1,last); } }

  4. Quicksort int partition(int* arrayOfInts, int first, int last) { int temp; int p = first; // set pivot = first index for (int k = first+1; k <= last; k++) // for every other indx { if (arrayOfInts[k] <= arrayOfInts[first]) // if data is smaller { p = p + 1; // update final pivot location swap(arrayOfInts[k], arrayOfInts[p]); } } swap(arrayOfInts[p], arrayOfInts[first]); return p; }

  5. 9 9 9 18 5 5 5 18 3 3 3 18 20 20 20 3 5 9 18 20 Partition Step Through partition(cards, 0, 4) P = 0 K = 1 P = 1 K = 3 cards[1] < cards[0] ? No cards[3] < cards[0]? Yes P = 2 P = 0 K = 2 temp = cards[3] cards[2] < cards[0] ? Yes cards[3] = cards[2] P = 1 cards[2] = cards[3] temp = cards[2] P = 2 K = 4 cards[2] = cards[1] cards[4] < cards[0]? No cards[1] = temp temp = cards[2], cards[2] = cards[first] cards[first] = temp, return p = 2;

  6. Complexity of Quicksort • Worst case is O(n2) • What does worst case correspond to? • Already sorted or near sorted • Partitioning leaves heavily unbalanced subarrays • On average is O(n log2n), and it is average a lot of the time.

  7. Complexity of Quicksort Recurrence Relation: [Average Case] 2 sub problems ½ size (if good pivot) Partition is O(n) a = 2 b = 2 k = 1 2 = 21 Master Theorem: O(nlog2n)

  8. Complexity of Quicksort Recurrence Relation: [Worst Case] • Partition separates into (n-1) and (1) • Can’t use master theorem: b (subproblem size) changes n-1/n n-2/n-1 n-3/n-2 • Note that sum of partition work: n + (n-1) + (n-2) + (n-3) … Sum(1,N) = N(N+1)/2 = O(N2)

  9. Complexity of Quicksort • Requires stack space to implement recursion • Worst case: O(n) stack space • If pivot breaks into 1 element and n-1 element subarrays • Average case: O(log n) • Pivot splits evenly

  10. MergeSort • General Mergesort Algorithm: • Recursively split subarrays in half • Merge sorted subarrays • Splitting is first in recursive call, so continues until have one item subarrays • One item subarrays are by definition sorted • Merge recombines subarrays so result is sorted • 1+1 item subarrays => 2 item subarrays • 2+2 item subarrays => 4 item subarrays • Use fact that subarrays are sorted to simplify merge algorithm

  11. MergeSort void mergesort(int* array, int* tempArray, int low, int high, int size) { if (low < high) { int middle = (low + high) / 2; mergesort(array,tempArray,low,middle, size); mergesort(array,tempArray,middle+1, high, size); merge(array,tempArray,low,middle,high, size); } }

  12. MergeSort void merge(int* array, int* tempArray, int low, int middle, int high, int size) { int i, j, k; for (i = low; i <= high; i++) { tempArray[i] = array[i]; } // copy into temp array i = low; j = middle+1; k = low; while ((i <= middle) && (j <= high)) { // merge if (tempArray[i] <= tempArray[j]) // if lhs item is smaller array[k++] = tempArray[i++]; // put in final array, increment else // final array position, lhs index array[k++] = tempArray[j++]; // else put rhs item in final array } // increment final array position // rhs index while (i <= middle) // one of the two will run out array[k++] = tempArray[i++]; // copy the rest of the data } // only need to copy if in lhs array // rhs array already in right place

  13. MergeSort Example 20 3 18 9 5 Recursively Split 20 3 18 9 5

  14. MergeSort Example 20 3 18 9 5 Recursively Split 9 20 3 18 5

  15. MergeSort Example 20 3 18 9 5 Merge

  16. 3 k Merge Sort Example 2 cards Not very interesting Think of as swap 20 3 3 20 Temp Array Array Temp[i] < Temp[j] Yes 3 20 18 j i

  17. Array 3 18 20 k MergeSort Example Temp Array Array Temp[i] < Temp[j] No 3 20 18 3 18 j k i Update J, K by 1 => Hit Limit of Internal While Loop, as J > High Now Copy until I > Middle

  18. 5 9 3 5 9 18 20 i=3,j=5 i=1,j=3 i=1,j=4 i=1,j=5 i=2,j=5 MergeSort Example 2 Card Swap 9 5 5 9 3 18 20 Final after merging above sets i=0,j=3

  19. Complexity of MergeSort Recurrence relation: 2 subproblems ½ size Merging is O(n) for any subproblem Always moving forwards in the array a = 2 b = 2 k = 1 2 = 21 Master Theorem: O(n log2n) Always O(n log2n) in both average and worst case Doesn’t rely on quality of pivot choice

  20. Space Complexity of Mergesort • Need an additional O(n) temporary array • Number of recursive calls: • Always O(log2n)

  21. Tradeoffs • When it is more useful to: • Just search • Quicksort or Mergesort and search • Assume Z searches Search on random data: Z * O(n) Fast Sort and binary search: O(nlog2n) + Z *log2n

  22. Tradeoffs Z * n <= nlog2n + Zlog2n Z(n - log2n) <= n log2n Z <= (n log2n) / (n-log2n) Z <= (n log2n) / n [Approximation] Z <= log2n [Approximation] Where as before, had to do N searches to make up for cost of sorting, now only do log2N 1,000,000 items = 19 searches, instead of 1,000,000

  23. How Fast? • Without specific details of what sorting, O(n log2n) is the maximum speed sort possible. • Only available operations: Compare, Swap • Proof: Decision Tree – describes how sort operates • Every vertex represents a comparison, every branch a result • Moving down tree – Tracing a possible run through the algorithm

  24. How Fast? K1 <= K2 [1,2,3] Yes No K2 <= K3 K1 <= K3 [2,1,3] [1,2,3] Yes No Yes No [2,3,1] [1,2,3] [2,1,3] stop K2 <= K3 stop K1 <= K3 [1,3,2] Yes Yes No No stop stop stop stop [1,3,2] [3,1,2] [2,3,1] [3,2,1]

  25. How Fast? • There are n! possible “stop” nodes – effectively all permutations of the n numbers in the array. • Thus any decision tree representing a sorting algorithm must have n! leaves • The height of a this type of tree (a binary tree) is correlated with number of leaves: • Height k = 2^(k-1) leaves • Must be at least log2n! + 1 height

  26. How Fast? • Path from top to bottom of tree – trace of a run of the algorithm • Need to prove that (log2n!) is lower bounded by (n log2n) n! = (n)(n-1)(n-2)(n-3) … (3)(2)(1) > (n)(n-1)(n-2)(n-3) … ceil(n/2) // doing fewer multiplies > ceil(n/2) (ciel(n/2)) // doing multiplies of bigger things > approximately (n/2)(n/2) log 2 n! > log 2 (n/2)(n/2) log 2 n! > (n/2) log 2 (n/2) //exponentiation in logs = multiplication out front log 2 n! > (n/2)(log2n – log2 2) // division in logs = subtraction log 2 n! > (n/2)(log2n – 1) log 2 n! > (n/2)(log2n) – (n/2) log 2 n! > (1/2) [nlog2n – n] log 2 n! ~ O(n log2n)

More Related