1 / 108

UNIT-II

ANALYSIS AND DESIGN OF ALGORITHMS. UNIT-II. CHAPTER 4:. DIVIDE –AND- CONQUER. OUTLINE. Divide – and - Conquer Technique Merge sort Quick sort Binary Search Multiplication of Large Integers and Strassen’s Matrix Multiplication. Divide – and – Conquer :.

bella
Download Presentation

UNIT-II

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. ANALYSIS AND DESIGN OF ALGORITHMS UNIT-II CHAPTER 4: DIVIDE –AND- CONQUER

  2. OUTLINE • Divide – and - Conquer Technique • Merge sort • Quick sort • Binary Search • Multiplication of Large Integers and Strassen’s Matrix Multiplication

  3. Divide – and – Conquer : Divide – and - conquer algorithms work according to the following general plan : 1. A problem’s instance is divided into several smaller instances of the same problem, ideally of about the same size. 2.The smaller instances are solved (typically recursively). 3. The solutions obtained for the smaller instances are combined to get a solution to the original problem.

  4. Figure: Divide – and – Conquer Technique.

  5. Divide – and – Conquer : • Not every divide-and-conquer algorithm is necessarily more efficient than even a brute-force solution. • The divide-and-conquer approach yields some of the most important and efficient algorithms in computer science. • Divide-and-Conquer technique is ideally suited for parallel computations, in which each subproblem can be solved simultaneously by its own processor. Later all solutions can be merged to get solution to original problem. Thus, the execution speed of a program which is based on this technique can be improved significantly.

  6. Divide – and – Conquer : • In the most typical case of divide-and-conquer, a problem’s instance of size n is divided into two instances of size n/2. • Generally, an instance of size n can be divided into b instances of size n/b, with a of them needing to be solved. (Here, a and b are constants; a ≥ 1 and b > 1). • Assuming that size n is a power of b, we get the following recurrence for the running time T (n): T (n) = aT (n/b) + f (n) ………….. (1) (General Divide-and-Conquer Recurrence) where f (n) is a function that accounts for the time spent on dividing the problem into smaller ones and on combining their solutions.

  7. Divide – and – Conquer : MASTER THEOREM: If f(n) ЄΘ(nd) with d ≥ 0 in recurrence Equation (1), Then, Θ(nd) if a < bd T(n) ЄΘ(nd log n) if a = bd Θ(nlogba) if a > bd

  8. Divide – and – Conquer : Example1: Consider the problem of computing the sum of n numbers stored in an array. ALGORITHM Sum(A[0…n-1], low, high) //Determines sum of n numbers stored in an array A //using divide-and-conquer technique recursively. //Input: An array A[0…n-1], low and high initialized to 0 and n-1 // respectively. //Output: Sum of all the elements in the array. if low = high return A[low] mid ← (low + high)/2 return (Sum(A, low, mid) + Sum(A, mid+1, high))

  9. Example: 4, 3, 2, 1 10 + 4, 3 2, 1 7 + 3 + 4 3 2 1 A, 0, 3 10 A, 0, 1 A, 2, 3 7 3 A, 2, 2 A, 3, 3 A, 0, 0 A, 1, 1 3 1 2 4 Recursion Tree:

  10. Analysis of the algorithm to find the sum of all the elements of the array using divide-and-Conquer technique Since the problem instance is divided into two parts, the recurrence relation for this algorithm is: A(n) = 0 if n = 1 A(n/2) + A(n/2) + 1 otherwise No. of additions No. of additions to add the sum of on left part of array on right part of array left and right part

  11. Analysis of the algorithm to find the sum of all the elements of the array using divide-and-Conquer technique Solve the below recurrence equation using Backward substitution method: A(1) = 0 (Initial Condition) A(n) = 2 A(n/2) + 1 A(n) = 2 A(n/2) + 1 … (1) = 2[ 2 A(n/4) + 1 ] + 1 replacing n by n/2 in (1) = 22 A(n/22) + 2 + 1 A(n/2) = 2 A(n/4) + 1 = 22[ 2 A(n/23) + 1 ] + 2 + 1 replacing n by n/22 in (1) = 23 A(n/23) + 22 + 2 + 1 A(n/22) = 2 A(n/23) + 1 = 2i A(n/2i) + 2i-1 + 2i-2 + . . . + 2 + 1 a(rn – 1) = 1 (2i – 1) =2i A(n/2i) + 2i – 1 r – 1 2 -1 substituting 2i by n in above step yields, n A(n/n) + n – 1 = n A(1) + n – 1 = n . 0 + n – 1 A(n) ЄΘ(n)

  12. Analysis of the algorithm to find the sum of all the elements of the array using divide-and-Conquer technique The recurrence equation for the number of additions A(n) made by the divide-and-conquer summation algorithm on inputs of size n = 2kis A(n) = 2A(n/2) + 1. Applying Master Theorem to above equation, Thus, for this example, a = 2, b = 2, and d = 0 hence, since a >bd, A(n) Єθ(nlogb a) = θ(nlog2 2) A(n) Єθ(n).

  13. Divide – and – Conquer : Example2: Consider the problem of finding the largest element in an array. ALGORITHM Large(A[0…n-1], low, high) //Determines the largest element in an array A using divide-and- //conquer technique recursively. //Input: An array A[0…n-1], low and high initialized to 0 and n-1 respectively. //Output: Largest element in the array. if low = high return A[low] mid ← (low + high)/2 n1 ← Large(A, low, mid) n2 ← Large(A, mid+1, high) if n1 > n2 return n1 else return n2

  14. Mergesort • The strategy behind Merge Sort is to change the problem of sorting into the problem of merging two sorted sub-lists into one. • If the two halves of the array were sorted, then merging them carefully could complete the sort of the entire list. 4, 3, 2, 1 4, 3 2, 1 4 3 2 1 3, 4 1, 2 1, 2, 3, 4

  15. Mergesort • Merge Sort is a "recursive" algorithm because it accomplishes its task by calling itself on a smaller version of the problem (only half of the list). • For example, if the array had 2 entries, Merge Sort would begin by calling itself for item 1. Since there is only one element, that sub-list is sorted and it can go on to call itself in item 2. • Since that also has only one item, it is sorted and now Merge Sort can merge those two sub-lists into one sorted list of size two.

  16. Mergesort • The real problem is how to merge the two sub-lists. • While it can be done in the original array, the algorithm is muchsimpler if it uses a separate array to hold the portion that has been merged and then copies the merged data back into the original array. • The basic philosophy of the merge is to determine which sub-list starts with the smallest data and copy that item into the merged list and move on to the next item in the sub-list.

  17. Mergesort ALGORITHM Mergesort(A[0…n-1]) //Sorts array A[0…n-1] by recursive mergesort //Input: An array A[0…n-1] of orderable elements //Output: Array A[0…n-1] sorted in nondecreasing order if n > 1 copy A[0 . . . n/2 - 1] to B[0 . . . n/2 - 1] copy A[ n/2 . . . n - 1] to C[0 . . . n/2 – 1] Mergesort(B[0 . . . n/2 – 1]) Mergesort(C[0 . . . n/2 – 1]) Merge(B, C, A)

  18. Mergesort ALGORITHM Merge(B[0 . . . p-1], C[0 . . . q-1], A[0 . . . p + q - 1]) //Merges two sorted arrays into one sorted array //Input: Arrays B[0 . . . p-1] and C[0 . . . q-1] both sorted //Output: Sorted array A[0 . . . p + q - 1] of the elements of B & C i ← 0, j ← 0, k ← 0 while i < p and j < q do if B[i] ≤ C[j] A[k] ← B[i]; i ← i + 1 else A[k] ← C[j]; j ← j + 1 k ← k + 1 if i = p copy C[j . . . q – 1] to A[k . . . p + q – 1] else copy B[i . . . p – 1] to A[k . . . p + q – 1]

  19. Mergesort #include<stdio.h> #include<conio.h> void mergesort(int *,int,int); void merge(int *,int,int,int); void main() { int i,a[10],n; clrscr(); printf("enter n value\n"); scanf("%d",&n); printf("enter values\n"); for(i=0;i<n;i++) scanf("%d",&a[i]); mergesort(a,0,n-1); printf("\nSorted array\n"); for(i=0;i<n;i++) printf("%d\t",a[i]); getch(); }

  20. Mergesort void mergesort(int *a,int low,int high) { int mid; if(low<high) { mid=(low+high)/2; mergesort(a,low,mid); mergesort(a,mid+1,high); merge(a,low,mid+1,high); } }

  21. Mergesort void merge(int *a,int low,int mid,int high) { int i,j,k,m,temp[20]; i=low,j=mid,k=-1; while(i<=mid-1 && j<=high) { if(a[i]<a[j]) temp[++k]=a[i++]; else temp[++k]=a[j++]; }

  22. Mergesort // copy remaining elements into temp array for(m=i;m<=mid-1;m++) temp[++k]=a[m]; for(m=j;m<=high;m++) temp[++k]=a[m]; // copy elements of temp array back into array a for(m=0;m<=k;m++) a[low+m]=temp[m]; }

  23. 7 2 9 4  2 4 7 9 3 8 6 1  1 3 8 6 7 2  2 7 9 4  4 9 3 8  3 8 6 1  1 6 7  7 2  2 9  9 4  4 3  3 8  8 6  6 1  1 Execution Example • Partition 7 2 9 4  3 8 6 11 2 3 4 6 7 8 9

  24. 7 2  2 7 9 4  4 9 3 8  3 8 6 1  1 6 7  7 2  2 9  9 4  4 3  3 8  8 6  6 1  1 Execution Example (cont.) • Recursive call, partition 7 2 9 4  3 8 6 11 2 3 4 6 7 8 9 7 2  9 4 2 4 7 9 3 8 6 1  1 3 8 6

  25. 7  7 2  2 9  9 4  4 3  3 8  8 6  6 1  1 Execution Example (cont.) • Recursive call, partition 7 2 9 4  3 8 6 11 2 3 4 6 7 8 9 7 2  9 4 2 4 7 9 3 8 6 1  1 3 8 6 7  2 2 7 9 4  4 9 3 8  3 8 6 1  1 6

  26. 7  2 2 7 9 4  4 9 3 8  3 8 6 1  1 6 Execution Example (cont.) • Recursive call, base case 7 2 9 4  3 8 6 11 2 3 4 6 7 8 9 7 2  9 4 2 4 7 9 3 8 6 1  1 3 8 6 77 2  2 9  9 4  4 3  3 8  8 6  6 1  1

  27. Execution Example (cont.) • Recursive call, base case 7 2 9 4  3 8 6 11 2 3 4 6 7 8 9 7 2  9 4 2 4 7 9 3 8 6 1  1 3 8 6 7  2 2 7 9 4  4 9 3 8  3 8 6 1  1 6 77 22 9  9 4  4 3  3 8  8 6  6 1  1

  28. Execution Example (cont.) • Merge 7 2 9 4  3 8 6 11 2 3 4 6 7 8 9 7 2  9 4 2 4 7 9 3 8 6 1  1 3 8 6 7  22 7 9 4  4 9 3 8  3 8 6 1  1 6 77 22 9  9 4  4 3  3 8  8 6  6 1  1

  29. Execution Example (cont.) • Recursive call, …, base case, merge 7 2 9 4  3 8 6 11 2 3 4 6 7 8 9 7 2  9 4 2 4 7 9 3 8 6 1  1 3 8 6 7  22 7 9 4 4 9 3 8  3 8 6 1  1 6 77 22 9 9 44 3  3 8  8 6  6 1  1

  30. Execution Example (cont.) • Merge 7 2 9 4  3 8 6 11 2 3 4 6 7 8 9 7 2  9 42 4 7 9 3 8 6 1  1 3 8 6 7  22 7 9 4 4 9 3 8  3 8 6 1  1 6 77 22 9 9 44 3  3 8  8 6  6 1  1

  31. Execution Example (cont.) • Recursive call, …, merge, merge 7 2 9 4  3 8 6 11 2 3 4 6 7 8 9 7 2  9 42 4 7 9 3 8 6 1 1 3 6 8 7  22 7 9 4 4 9 3 83 8 6 1 1 6 77 22 9 9 4 4 33 88 66 11

  32. Execution Example (cont.) • Merge 7 2 9 4  3 8 6 11 2 3 4 6 7 8 9 7 2  9 42 4 7 9 3 8 6 1 1 3 6 8 7  22 7 9 4 4 9 3 83 8 6 1 1 6 77 22 9 9 44 33 88 66 11

  33. Mergesort Example: 4, 3, 2, 1 A, 0, 3 A, 2, 3 A, 0, 1 4, 3 2, 1 A, 0, 0 A, 1, 1 A, 2, 2 A, 3, 3 4 3 2 1 A, 2, 3, 3 A, 0, 1, 1 3, 4 1, 2 A, 0, 2, 3 1, 2, 3, 4 Recursion Tree:

  34. Analysis of Mergesort • Assuming that n is a power of 2, the recurrence relation for the number of key comparisons C(n) is C(n) = 2C(n/2) + Cmerge(n) for n > 1, C(1) = 0. where, Cmerge(n) is the number of key comparisons performed during the merging stage. • For the worst case, Cmerge(n) = n – 1, and we have the recurrence Cworst(n) = 2Cworst(n/2) + n – 1 for n > 1, Cworst(1) = 0. • Hence, according to the Master Theorem, Cworst(n) ЄΘ(n log n) (Here, a=2, b=2, d=1) (Since, a = bd, Cworst(n) ЄΘ(nd log n))

  35. Quick sort divides the inputs according to their value to achieve its partition, a situation where all the elements before some position s are smaller than or equal to A[s] and all the elements after position s are greater than or equal to A[s]: A[0] . . . A[s – 1] A[s] A[s + 1] . . . A[n – 1] all are ≤ A[s] all are ≥ A[s] After a partition has been achieved, A[s] will be in its final position in the sorted array, and we can continue sorting the two subarrays of the elements preceding and following A[s] independently by using same method. Quick Sort

  36. Quick Sort ALGORITHM Quicksort(A[l..r]) //Sorts a subarray by quicksort //Input: A subarray A[l..r] of A[0..n - 1], defined by its left // and right indices l and r //Output: The subarray A[l..r] sorted in nondecreasing // order if l < r s  Partition(A[l..r]) //s is a split position Quicksort(A[l..s - 1]) Quicksort(A[s + 1..r])

  37. Quick Sort • The hard part of Quick Sort is the partitioning. • Algorithm looks at the first element of the array (called the "pivot"). It will put all of the elements which are less than the pivot in the lower portion of the array and the elements higher than the pivot in the upper portion of the array. When that is complete, it can put the pivot between those sections and Quick Sort will be able to sort the two sections separately.

  38. Procedure to achieve partition: • First, we select pivot element p with respect to whose value we are going to divide the subarray ( Usually, first element in the subarray is taken as pivot). • The elements in the subarray are rearranged to achieve partition by using an efficient method based on left-to-right scan and right-to-left scan, each comparing the subarray’s element with the pivot. • The left-to-right scan, denoted by index i starts with the second element. This scan skips over elements that are smaller than the pivot and stops on encountering the first element greater than or equal to the pivot. • The right-to-left scan, denoted by index j starts with the last element. • This scan skips over elements that are larger than the pivot and stops • on encountering the first element smaller than or equal to the pivot.

  39. Procedure to achieve partition: • After both scans stop, three situations may arise, depending on whether or not the scanning indices have crossed: • If scanning indices i and j have not crossed, i.e., i < j, we simply exchange A[i] and A[j] and resume the scans by incrementing i and decrementing j: • If the scanning indices have crossed over, i.e., i > j, we will have partitioned the array after exchanging the pivot with A[j]: i j p all are ≤ p > p. . . < p all are ≥ p j i p all are ≤ p ≤ p≥ p all are ≥ p

  40. Procedure to achieve partition: • Finally, if the scanning indices stop while pointing to the same element, i.e., i=j, the value they are pointing to must be equal to p. Thus we have the array partitioned, with the split position s = i = j: We can combine this case with the case of crossed-over indices (i>j) by exchanging the pivot with A[j] whenever i ≥ j. i=j p all are ≤ p = p all are ≥ p

  41. Partition Procedure ALGORITHM Partition(A[l..r]) //Partitions subarray by using its first element as a pivot //Input: subarray A[l..r] of A[0..n - 1], defined by its left and right indices l and r (l< r) //Output: A partition of A[l..r], with the split position returned as this function’s value p  A[l] i  l; j  r + 1 repeat repeat i  i + 1 until A[i] ≥ p repeat j j -1 until A[j ] ≤ p swap(A[i], A[j ]) until i ≥ j swap(A[i], A[j ]) //undo last swap when i ≥ j swap(A[l], A[j ]) return j

  42. While A[i] <= A[pivot] • ++i 40 20 10 80 60 50 7 30 100 Pivot_index = 0 [0] [1] [2] [3] [4] [5] [6] [7] [8] i j

  43. While A[i] <= A[pivot] • ++i 40 20 10 80 60 50 7 30 100 pivot_index = 0 [0] [1] [2] [3] [4] [5] [6] [7] [8] i j

  44. While A[i] <= A[pivot] • ++i 40 20 10 80 60 50 7 30 100 pivot_index = 0 [0] [1] [2] [3] [4] [5] [6] [7] [8] i j

  45. While A[i] <= A[pivot] • ++i • While A[j] > A[pivot] • - - j 40 20 10 80 60 50 7 30 100 pivot_index = 0 [0] [1] [2] [3] [4] [5] [6] [7] [8] i j

  46. While A[i] <= A[pivot] • ++i • While A[j] > A[pivot] • - - j 40 20 10 80 60 50 7 30 100 pivot_index = 0 [0] [1] [2] [3] [4] [5] [6] [7] [8] i j

  47. While A[i] <= A[pivot] • ++i • While A[j] > A[pivot] • - - j • If i < j • Swap A[i] and A[j] 40 20 10 80 60 50 7 30 100 pivot_index = 0 [0] [1] [2] [3] [4] [5] [6] [7] [8] i j

  48. While A[i] <= A[pivot] • ++i • While A[j] > A[pivot] • - - j • If i < j • Swap A[i] and A[j] 40 20 10 30 60 50 7 80 100 pivot_index = 0 [0] [1] [2] [3] [4] [5] [6] [7] [8] i j

  49. While A[i] <= A[pivot] • ++i • While A[j] > A[pivot] • - - j • If i < j • Swap A[i] and A[j] • 4. While j > i goto step 1 40 20 10 30 60 50 7 80 100 pivot_index = 0 [0] [1] [2] [3] [4] [5] [6] [7] [8] i j

  50. While A[i] <= A[pivot] • ++i • While A[j] > A[pivot] • - - j • If i < j • Swap A[i] and A[j] • 4. While j > i goto step 1 40 20 10 30 60 50 7 80 100 pivot_index = 0 [0] [1] [2] [3] [4] [5] [6] [7] [8] i j

More Related