Mergesort and Quicksort
LAST TODAY NEXT Binary search Divide and conquer Part II of course • mergesort and quicksort • Data structures Recursion Randomness
Recall: Complexity of binary search Worst case: O(log n) Best case: O(1)
Review Algorithm Complexity Linear search O(n) Binary search O(log n) Why do we get a logarithmic speed up in moving from linear search to binary search?
Review Algorithm Complexity Linear search O(n) Selection sort O(n 2 ) Binary search O(log n)
Algorithm Complexity In Practice … Linear search O(n) Selection sort O(n 2 ) Binary search O(log n) Suppose that Google sorts 10 9 pages, and examining each page takes 10 -9 seconds. How long does it take to sort all the pages using selection sort? (10 9 ) 2 * 10 -9 = 10 9 more than 3 years
Warm-up exercise Suppose we sort each half separately, and then combine them with an O(n) algorithm. If we used an O(n 2 ) algorithm for sorting, for an input of size n, how many steps would it take to sort the two halves? n sort n/2 elements n/2 elements each half sorted sorted sorting the first half: _________ steps sorting the second half: _________ steps
Doing less work for sorting n/2n/2 nn/2 sort each half sorted sorted work size of input (number of steps) n n 2 n/2 n 2 /4
Divide and conquer for sorting
Divide and conquer n/2n/2 nn/2 sort each half sorted sorted merge two halves n/2sorted
Toward implementation lo mid hi n
lo mid hi n void selection_sort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); ; void sort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); { int mid = lo + (hi - lo)/2; //@assert … selection_sort(A, lo, mid); //@assert is_sorted(A, lo, mid); selection_sort(A, mid, hi); //@assert is_sorted(A, mid, hi); … } Are the function calls safe?
lo mid hi n void selection_sort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); ; void sort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); { int mid = lo + (hi - lo)/2; //@assert lo <= mid && mid <= hi; selection_sort(A, lo, mid); //@assert is_sorted(A, lo, mid); selection_sort(A, mid, hi); //@assert is_sorted(A, mid, hi); … }
lo mid hi n void selection_sort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); ; void sort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); { int mid = lo + (hi - lo)/2; //@assert lo <= mid && mid <= hi; selection_sort(A, lo, mid); //@assert is_sorted(A, lo, mid); selection_sort(A, mid, hi); //@assert is_sorted(A, mid, hi); … } void merge(int[] A, int lo, int mid, int hi) //@requires 0 <= lo && lo <= mid && mid <= hi && hi <= \length(A); //@requires is_sorted(A, lo, mid) && is_sorted(A, mid, hi); //@ensures is_sorted(A, lo, hi);
void selection_sort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); ; void sort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); { int mid = lo + (hi - lo)/2; //@assert lo <= mid && mid <= hi; selection_sort(A, lo, mid); //@assert is_sorted(A, lo, mid); selection_sort(A, mid, hi); //@assert is_sorted(A, mid, hi); merge(A, lo, mid, hi); //@assert is_sorted(A, lo, hi); } void merge(int[] A, int lo, int mid, int hi) //@requires 0 <= lo && lo <= mid && mid <= hi && hi <= \length(A); //@requires is_sorted(A, lo, mid) && is_sorted(A, mid, hi); //@ensures is_sorted(A, lo, hi);
void selection_sort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); ; void sort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); { int mid = lo + (hi - lo)/2; //@assert lo <= mid && mid <= hi; selection_sort(A, lo, mid); //@assert is_sorted(A, lo, mid); selection_sort(A, mid, hi); //@assert is_sorted(A, mid, hi); merge(A, lo, mid, hi); //@assert is_sorted(A, lo, hi); } Suppose merge is O(n), what is the complexity of sort ? O(n 2 ) + O(n) = O(n 2 )
Mergesort
Some observations void selection_sort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); ; same contracts void sort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); { int mid = lo + (hi - lo)/2; //@assert lo <= mid && mid <= hi; selection_sort(A, lo, mid); selection_sort(A, mid, hi); merge(A, lo, mid, hi); } We can use sort instead of selection_sort recursively!
Recursive function void sort (int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); { int mid = lo + (hi - lo)/2; //@assert lo <= mid && mid <= hi; sort (A, lo, mid); sort (A, mid, hi); merge(A, lo, mid, hi); //@assert is_sorted(A, lo, hi); }
Recursive merge sort void merge(int[] A, int lo, int mid, int hi) //@requires 0 <= lo && lo <= mid && mid <= hi && hi <= \length(A); //@requires is_sorted(A, lo, mid) && is_sorted(A, mid, hi); //@ensures is_sorted(A, lo, hi); ; void mergesort (int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); { int mid = lo + (hi - lo)/2; //@assert lo <= mid && mid <= hi; mergesort (A, lo, mid); mergesort (A, mid, hi); merge(A, lo, mid, hi); } How can we reason about correctness of recursive code?
A problem? void merge(int[] A, int lo, int mid, int hi) //@requires 0 <= lo && lo <= mid && mid <= hi && hi <= \length(A); //@requires is_sorted(A, lo, mid) && is_sorted(A, mid, hi); //@ensures is_sorted(A, lo, hi); ; void mergesort (int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); { int mid = lo + (hi - lo)/2; //@assert lo <= mid && mid <= hi; mergesort (A, lo, mid); mergesort (A, mid, hi); merge(A, lo, mid, hi); }
Adding a base case void mergesort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); { if (hi - lo <= 1) return; int mid = lo + (hi - lo)/2; //@assert lo <= mid && mid <= hi; mergesort(A, lo, mid); //@assert is_sorted(A, lo, mid); mergesort(A, mid, hi); //@assert is_sorted(A, mid, hi); merge(A, lo, mid, hi); }
Adding a base case void mergesort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); { if (hi - lo <= 1) return; int mid = lo + (hi - lo)/2; //@assert lo < mid && mid < hi; mergesort(A, lo, mid); //@assert is_sorted(A, lo, mid); mergesort(A, mid, hi); //@assert is_sorted(A, mid, hi); merge(A, lo, mid, hi); }
void mergesort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); { if (hi - lo <= 1) return; Complexity int mid = lo + (hi - lo)/2; //@assert lo < mid && mid < hi; mergesort(A, lo, mid); //@assert is_sorted(A, lo, mid); mergesort(A, mid, hi); //@assert is_sorted(A, mid, hi); merge(A, lo, mid, hi); } merge 1 array of size n 2 arrays of size n/2 n/2 arrays of size 2 merge n arrays of size 1
void mergesort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); { if (hi - lo <= 1) return; How many levels are there? int mid = lo + (hi - lo)/2; //@assert lo < mid && mid < hi; mergesort(A, lo, mid); //@assert is_sorted(A, lo, mid); mergesort(A, mid, hi); //@assert is_sorted(A, mid, hi); merge(A, lo, mid, hi); } O(n) 1 array of size n O(n) 2 arrays of size n/2 n/2 arrays of size 2 O(n) n arrays of size 1
void mergesort(int[] A, int lo, int hi) //@requires 0 <= lo && lo <= hi && hi <= \length(A); //@ensures is_sorted(A, lo, hi); { if (hi - lo <= 1) return; How many levels are there? int mid = lo + (hi - lo)/2; //@assert lo < mid && mid < hi; mergesort(A, lo, mid); //@assert is_sorted(A, lo, mid); mergesort(A, mid, hi); //@assert is_sorted(A, mid, hi); merge(A, lo, mid, hi); } 1 array of size n 2 arrays of size n/2 O(n log n) n/2 arrays of size 2 n arrays of size 1
Recommend
More recommend