820 likes | 951 Vues
This lecture covers essential concepts of recursive algorithms, focusing on the Merge Sort technique. We discuss how to break down sorting problems using the Divide and Conquer method, addressing the algorithm's structure, including the base cases and recursive calls. We analyze the efficiency class of Merge Sort, highlighting its time complexity of O(n log n) and space complexity of O(n). Suggestions for improving sorting algorithms, including Quick Sort, will also be explored, along with a review of basic operations and their execution frequencies.
E N D
Quiz 2 Input: A nonnegative integer n S:=0 for i:=0 to n do S:=S + i*i return S • What Doest this Algorithm Compute • What is its basic operation • How many times is the basic operation executed? • What is the efficiency class of this algorithm • Suggest an improvement or a better algorithm and its efficiency class
Divide and Conquer • Merge Sort • Quick Sort
Divide and Conquer • Base Case, solve the problem directly if it is small enough • Divide the problem into two or more similar and smaller subproblems • Recursively solve the subproblems • Combine solutions to the subproblems
Divide and Conquer - Sort Problem: • Input: A[left..right] – unsorted array of integers • Output:A[left..right] – sorted in non-decreasing order
Divide and Conquer - Sort • Base case • at most one element (left ≥ right), return • DivideA into twosubarrays: FirstPart, SecondPart • Two Subproblems: • sort the FirstPart • sort the SecondPart • Recursively • sort FirstPart • sort SecondPart • Combinesorted FirstPart and sorted SecondPart
Overview • Divide and Conquer • Merge Sort • Quick Sort
Merge Merge Sort: Idea Divide into two halves A FirstPart SecondPart Recursively sort SecondPart FirstPart A is sorted!
Merge Sort: Algorithm • Merge-Sort(A, left, right) • if left ≥ right return • else • middle ←(left+right)/2 • Merge-Sort(A, left, middle) • Merge-Sort(A, middle+1, right) • Merge(A, left, middle, right) Recursive Call
Merge-Sort: Merge Sorted A: merge Sorted SecondPart SortedFirstPart A: A[right] A[left] A[middle]
5 15 28 30 6 10 14 5 2 3 7 8 1 4 5 6 R: L: 3 5 15 28 6 10 14 22 Temporary Arrays Merge-Sort: Merge Example A:
Merge-Sort: Merge Example A: 3 1 5 15 28 30 6 10 14 k=0 R: L: 3 2 15 3 7 28 30 8 6 1 10 4 5 14 22 6 i=0 j=0
Merge-Sort: Merge Example A: 2 1 5 15 28 30 6 10 14 k=1 R: L: 2 3 5 3 15 7 8 28 6 1 10 4 14 5 6 22 i=0 j=1
Merge-Sort: Merge Example A: 3 1 2 15 28 30 6 10 14 k=2 R: L: 2 3 7 8 6 1 10 4 5 14 22 6 i=1 j=1
Merge-Sort: Merge Example A: 1 2 3 6 10 14 4 k=3 R: L: 2 3 7 8 1 6 10 4 14 5 6 22 j=1 i=2
Merge-Sort: Merge Example A: 1 2 3 4 6 10 14 5 k=4 R: L: 2 3 7 8 1 6 10 4 14 5 6 22 i=2 j=2
Merge-Sort: Merge Example A: 6 1 2 3 4 5 6 10 14 k=5 R: L: 2 3 7 8 6 1 4 10 5 14 6 22 i=2 j=3
Merge-Sort: Merge Example A: 7 1 2 3 4 5 6 14 k=6 R: L: 2 3 7 8 1 6 10 4 14 5 22 6 i=2 j=4
Merge-Sort: Merge Example A: 8 1 2 3 4 5 6 7 14 k=7 R: L: 2 3 5 3 7 15 28 8 6 1 10 4 5 14 22 6 i=3 j=4
Merge-Sort: Merge Example A: 1 2 3 4 5 6 7 8 k=8 R: L: 3 2 3 5 15 7 8 28 1 6 10 4 14 5 22 6 j=4 i=4
Merge(A, left, middle, right) • n1 ← middle – left + 1 • n2 ← right – middle • create array L[n1], R[n2] • for i ← 0 to n1-1 do L[i] ← A[left +i] • for j ← 0 to n2-1 do R[j] ← A[middle+j] • k ← i ← j ← 0 • while i < n1 & j < n2 • if L[i] < R[j] • A[k++] ← L[i++] • else • A[k++] ← R[j++] • while i < n1 • A[k++] ← L[i++] • while j < n2 • A[k++] ← R[j++] n = n1+n2 Space: n Time : cn for some constant c
Merge-Sort(A, 0, 7) Divide A: 3 7 5 1 6 2 8 4 6 2 8 4 3 7 5 1
Merge-Sort(A, 0, 7) , divide Merge-Sort(A, 0, 3) A: 3 7 5 1 8 4 6 2 6 2 8 4
Merge-Sort(A, 0, 7) , divide Merge-Sort(A, 0, 1) A: 3 7 5 1 8 4 2 6 6 2
Merge-Sort(A, 0, 7) , base case Merge-Sort(A, 0, 0) A: 3 7 5 1 8 4 2 6
Merge-Sort(A, 0, 7) Merge-Sort(A, 0, 0), return A: 3 7 5 1 8 4 2 6
Merge-Sort(A, 0, 7) , base case Merge-Sort(A, 1, 1) A: 3 7 5 1 8 4 6 2
Merge-Sort(A, 0, 7) Merge-Sort(A, 1, 1), return A: 3 7 5 1 8 4 2 6
Merge-Sort(A, 0, 7) Merge(A, 0, 0, 1) A: 3 7 5 1 8 4 2 6
Merge-Sort(A, 0, 7) Merge-Sort(A, 0, 1), return A: 3 7 5 1 8 4 2 6
Merge-Sort(A, 0, 7) , divide Merge-Sort(A, 2, 3) A: 3 7 5 1 2 6 4 8 8 4
Merge-Sort(A, 0, 7) Merge-Sort(A, 2, 2), base case A: 3 7 5 1 2 6 4 8
Merge-Sort(A, 0, 7) Merge-Sort(A, 2, 2),return A: 3 7 5 1 2 6 4 8
Merge-Sort(A, 0, 7) Merge-Sort(A, 3, 3), base case A: 2 6 8 4
Merge-Sort(A, 0, 7) Merge-Sort(A, 3, 3), return A: 3 7 5 1 2 6 4 8
Merge-Sort(A, 0, 7) Merge(A, 2, 2, 3) A: 3 7 5 1 2 6 4 8
Merge-Sort(A, 0, 7) Merge-Sort(A, 2, 3), return A: 3 7 5 1 4 8 2 6
Merge-Sort(A, 0, 7) Merge(A, 0, 1, 3) A: 3 7 5 1 2 4 6 8
Merge-Sort(A, 0, 7) Merge-Sort(A, 0, 3), return A: 2 4 6 8 3 7 5 1
Merge-Sort(A, 0, 7) Merge-Sort(A, 4, 7) A: 2 4 6 8 3 7 5 1
Merge-Sort(A, 0, 7) Merge (A, 4, 5, 7) A: 2 4 6 8 1 3 5 7
Merge-Sort(A, 0, 7) Merge-Sort(A, 4, 7), return A: 2 4 6 8 1 3 5 7
Merge-Sort(A, 0, 7) Merge-Sort(A, 0, 7), done! Merge(A, 0, 3, 7) A: 1 2 3 4 5 6 7 8
Merge-Sort Analysis cn n 2 × cn/2 = cn n/2 n/2 log n levels 4 × cn/4 = cn n/4 n/4 n/4 n/4 n/2 × 2c = cn 2 2 2 Total: cn log n • Total running time:(nlogn) • Total Space: (n)
Merge-Sort Summary Approach: divide and conquer Time • Most of the work is in the merging • Total time: (n log n) Space: • (n), more space than other sorts.
Overview • Divide and Conquer • Merge Sort • Quick Sort
Quick Sort • Divide: • Pick any element p as the pivot, e.g, the first element • Partition the remaining elements into FirstPart,which contains all elements< p SecondPart, which contains all elements ≥ p • Recursively sort the FirstPart and SecondPart • Combine: no work is necessary since sorting is done in place
Partition Recursive call p p p p ≤ x p ≤ x Sorted FirstPart Sorted SecondPart x < p Quick Sort A: pivot FirstPart SecondPart x < p Sorted
Quick Sort Quick-Sort(A, left, right) ifleft ≥ right return else middle ← Partition(A, left, right) Quick-Sort(A, left, middle–1 ) Quick-Sort(A, middle+1, right) end if
p x < p p p ≤ x x < p p ≤ x p Partition A: A: A: p