Presentation is loading. Please wait.

Presentation is loading. Please wait.

Introduction to Algorithms Rabie A. Ramadan rabieramadan.org 4 Some of the sides are exported from different sources.

Similar presentations


Presentation on theme: "Introduction to Algorithms Rabie A. Ramadan rabieramadan.org 4 Some of the sides are exported from different sources."— Presentation transcript:

1 Introduction to Algorithms Rabie A. Ramadan rabie@rabieramadan.org http://www. rabieramadan.org 4 Some of the sides are exported from different sources to clarify the topic

2 Chapter 4 Divide-and-Conquer Copyright © 2007 Pearson Addison-Wesley. All rights reserved. Acknowledgment : Some of the slides are based on a tutorial made by Kruse and Ryba

3 Divide-and-Conquer The most-well known algorithm design strategy: 1. Divide instance of problem into two or more smaller instances 2. Solve smaller instances recursively 3. Obtain solution to original (larger) instance by combining these solutions

4 Divide-and-Conquer Technique (cont.) subproblem 2 of size n/2 subproblem 1 of size n/2 a solution to subproblem 1 a solution to the original problem a solution to subproblem 2 a problem of size n (instance) It general leads to a recursive algorithm!

5 Divide-and-Conquer Examples Sorting: mergesort and quicksort Binary tree traversals Binary search Multiplication of large integers Matrix multiplication: Strassen’s algorithm Closest-pair and convex-hull algorithms

6 General Divide-and-Conquer Recurrence General case analysis n Given a problem of size n (n/b) Assume that can be divided into b instances of size (n/b) a a problems of (n/b) are the one that solved f(n) The time needed for the dividing the problem and summing the solutions back is f(n) Time complexity of Divide and Conquer T(n) = aT(n/b) + f (n)

7 General Divide-and-Conquer Recurrence The complexity of divide and conquer depends on values of a and b T(n) = aT(n/b) + f (n) where f(n)   (n d ), d  0 Master Theorem: If a < b d, T(n)   (n d ) (Case 1) If a = b d, T(n)   (n d log n) (Case 2) If a = b d, T(n)   (n d log n) (Case 2) If a > b d, T(n)   (n log b a ) (Case 3) If a > b d, T(n)   (n log b a ) (Case 3) Note: The same results hold with O instead of .

8 Group Activity 8 Compute the Complexity of the following functions in terms of T(n) = 4T(n/2) + n  T(n)  ? T(n) = 4T(n/2) + n 2  T(n)  ? T(n) = 4T(n/2) + n 2  T(n)  ? T(n) = 4T(n/2) + n 3  T(n)  ? T(n) = 4T(n/2) + n 3  T(n)  ? T(n) = 2T(n/2) + 1  T(n)  ? T(n) = 2T(n/2) + 1  T(n)  ?  (n^2) Case 3  (n^2log n) Case 2  (n^3) Case 1   (n) Case 3

9 Mergesort Split array A[0..n-1] into about equal halves and make copies of each half in arrays B and C Sort arrays B and C recursively Merge sorted arrays B and C into array A as follows: Repeat the following until no elements remain in one of the arrays: compare the first elements in the remaining unprocessed portions of the arrays copy the smaller of the two into A, while incrementing the index indicating the unprocessed portion of that array Once all elements in one of the arrays are processed, copy the remaining unprocessed elements from the other array into A.

10 Pseudocode of Mergesort

11 Mergesort Example

12 Group Activity Write the Pseudocode of Merge part? Θ(p+q)Θ(n) Time complexity: Θ(p+q) = Θ(n) comparisons

13 Analysis of Mergesort At every step, I divide the elements by 2 b Then b =2 2 Also the number of problems to be solved with each subproblem every time is a= 2 f(n) ???? f(n) ???? F(n)(n-1) F(n) requires in the worst case almost (n-1) comparisons based * the number of recurrences. T(n) = 2T(n/2) + n-1 =??? T(n) = 2T(n/2) + n-1 =??? Space requirement: Θ(n) (not in-place) Space requirement: Θ(n) (not in-place) T(n) = 2T(n/2) + f(n), T(1) = 0 If a = b d, T(n)   (n d log n) =  (n log n)  (n log n)

14 Quicksort Select a pivot (partitioning element) – here, the first element Rearrange the list so that all the elements in the first s positions are smaller than or equal to the pivot and all the elements in the remaining n-s positions are larger than or equal to the pivot Exchange the pivot with the last element in the first (i.e.,  ) subarray — the pivot is now in its final position Sort the two subarrays recursively v S v S1S2

15 Dividing Process (s, i, j) For each partition, you select the pivot index, and first and last elements indexes (s, i, j) i i moves from left-to-right (looks for elements smaller than the pivot) j j moves from right-to-left (looks for elements greater than the pivot) When both stops, we got three cases : i< j  Swap (A[i], A[j]) i> j  array is partitioned Swap( pivot A[s], A[j]) i=j  A[i]=A[j]=A[s]

16 Example We are given array of n integers to sort: 402010806050730100

17 Pick Pivot Element There are a number of ways to pick the pivot element. In this example, we will use the first element in the array: 402010806050730100

18 Partitioning Array Given a pivot, partition the elements of the array such that the resulting array consists of: 1. One sub-array that contains elements >= pivot 2. Another sub-array that contains elements < pivot The sub-arrays are stored in the original data array. Partitioning loops through, swapping elements below/above pivot.

19 402010806050730100 pivot_index = 0 [0] [1] [2] [3] [4] [5] [6] [7] [8] too_big_index too_small_index

20 402010806050730100 pivot_index = 0 too_big_index too_small_index 1.While data[too_big_index] <= data[pivot] ++too_big_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

21 402010806050730100 pivot_index = 0 too_big_index too_small_index 1.While data[too_big_index] <= data[pivot] ++too_big_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

22 402010806050730100 pivot_index = 0 too_big_index too_small_index 1.While data[too_big_index] <= data[pivot] ++too_big_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

23 402010806050730100 pivot_index = 0 too_big_index too_small_index 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

24 402010806050730100 pivot_index = 0 too_big_index too_small_index 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

25 402010806050730100 pivot_index = 0 too_big_index too_small_index 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] [0] [1] [2] [3] [4] [5] [6] [7] [8]

26 402010306050780100 pivot_index = 0 too_big_index too_small_index 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] [0] [1] [2] [3] [4] [5] [6] [7] [8]

27 402010306050780100 pivot_index = 0 too_big_index too_small_index 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. [0] [1] [2] [3] [4] [5] [6] [7] [8]

28 402010306050780100 pivot_index = 0 too_big_index too_small_index 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. [0] [1] [2] [3] [4] [5] [6] [7] [8]

29 402010306050780100 pivot_index = 0 too_big_index too_small_index 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. [0] [1] [2] [3] [4] [5] [6] [7] [8]

30 402010306050780100 pivot_index = 0 too_big_index too_small_index 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. [0] [1] [2] [3] [4] [5] [6] [7] [8]

31 402010306050780100 pivot_index = 0 too_big_index too_small_index 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. [0] [1] [2] [3] [4] [5] [6] [7] [8]

32 402010306050780100 pivot_index = 0 too_big_index too_small_index 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. [0] [1] [2] [3] [4] [5] [6] [7] [8]

33 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 402010307506080100 pivot_index = 0 too_big_index too_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

34 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 402010307506080100 pivot_index = 0 too_big_index too_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

35 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 402010307506080100 pivot_index = 0 too_big_index too_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

36 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 402010307506080100 pivot_index = 0 too_big_index too_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

37 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 402010307506080100 pivot_index = 0 too_big_index too_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

38 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 402010307506080100 pivot_index = 0 too_big_index too_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

39 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 402010307506080100 pivot_index = 0 too_big_index too_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

40 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 402010307506080100 pivot_index = 0 too_big_index too_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

41 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 402010307506080100 pivot_index = 0 too_big_index too_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

42 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 5.Swap data[too_small_index] and data[pivot_index] 402010307506080100 pivot_index = 0 too_big_index too_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

43 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 5.Swap data[too_small_index] and data[pivot_index] 720103040506080100 pivot_index = 4 too_big_index too_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

44 Partition Result 720103040506080100 <= data[pivot]> data[pivot] [0] [1] [2] [3] [4] [5] [6] [7] [8]

45 Recursion: Quicksort Sub-arrays 720103040506080100 <= data[pivot]> data[pivot] [0] [1] [2] [3] [4] [5] [6] [7] [8]

46 Group Activity Write a pseudocode for the Quicksort ?

47 Partitioning Algorithm Θ(r-l) Time complexity: Θ(r-l) comparisons or i > r or j = l <

48 Quicksort Analysis Assume that keys are random, uniformly distributed. What is best case running time? Try it with your classmates ?

49 Quicksort Analysis Assume that keys are random, uniformly distributed. What is best case running time? Recursion: 1. Partition splits array in two sub-arrays of size n/2 2. Quicksort each sub-array

50 Quicksort Analysis Assume that keys are random, uniformly distributed. What is best case running time? Recursion: 1. Partition splits array in two sub-arrays of size n/2 2. Quicksort each sub-array Depth of recursion tree?

51 Quicksort Analysis Assume that keys are random, uniformly distributed. What is best case running time? Recursion: 1. Partition splits array in two sub-arrays of size n/2 2. Quicksort each sub-array Depth of recursion tree? O(log 2 n)

52 Quicksort Analysis Assume that keys are random, uniformly distributed. What is best case running time? Recursion: 1. Partition splits array in two sub-arrays of size n/2 2. Quicksort each sub-array Depth of recursion tree? O(log 2 n) Number of accesses in partition?

53 Quicksort Analysis Assume that keys are random, uniformly distributed. What is best case running time? Recursion: 1. Partition splits array in two sub-arrays of size n/2 2. Quicksort each sub-array Depth of recursion tree? O(log 2 n) Number of accesses in partition? O(n)

54 Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log 2 n)

55 Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log 2 n) Worst case running time?

56 Quicksort: Worst Case Assume first element is chosen as pivot. Assume we get array that is already in order: 24101213505763100 pivot_index = 0 [0] [1] [2] [3] [4] [5] [6] [7] [8] too_big_index too_small_index

57 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 5.Swap data[too_small_index] and data[pivot_index] 24101213505763100 pivot_index = 0 too_big_indextoo_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

58 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 5.Swap data[too_small_index] and data[pivot_index] 24101213505763100 pivot_index = 0 too_big_indextoo_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

59 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 5.Swap data[too_small_index] and data[pivot_index] 24101213505763100 pivot_index = 0 too_big_indextoo_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

60 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 5.Swap data[too_small_index] and data[pivot_index] 24101213505763100 pivot_index = 0 too_big_indextoo_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

61 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 5.Swap data[too_small_index] and data[pivot_index] 24101213505763100 pivot_index = 0 too_big_indextoo_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

62 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 5.Swap data[too_small_index] and data[pivot_index] 24101213505763100 pivot_index = 0 too_big_indextoo_small_index [0] [1] [2] [3] [4] [5] [6] [7] [8]

63 1.While data[too_big_index] <= data[pivot] ++too_big_index 2.While data[too_small_index] > data[pivot] --too_small_index 3.If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4.While too_small_index > too_big_index, go to 1. 5.Swap data[too_small_index] and data[pivot_index] 24101213505763100 pivot_index = 0 > data[pivot]<= data[pivot] [0] [1] [2] [3] [4] [5] [6] [7] [8]

64 Quick Sort 1-64

65 Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log 2 n) Worst case running time? Recursion: 1. Partition splits array in two sub-arrays: one sub-array of size 0 the other sub-array of size n-1 2. Quicksort each sub-array Depth of recursion tree?

66 Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log 2 n) Worst case running time? Recursion: 1. Partition splits array in two sub-arrays: one sub-array of size 0 the other sub-array of size n-1 2. Quicksort each sub-array Depth of recursion tree? O(n)

67 Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log 2 n) Worst case running time? Recursion: 1. Partition splits array in two sub-arrays: one sub-array of size 0 the other sub-array of size n-1 2. Quicksort each sub-array Depth of recursion tree? O(n) Number of accesses per partition?

68 Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log 2 n) Worst case running time? Recursion: 1. Partition splits array in two sub-arrays: one sub-array of size 0 the other sub-array of size n-1 2. Quicksort each sub-array Depth of recursion tree? O(n) Number of accesses per partition? O(n)

69 Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log 2 n) Worst case running time: O(n 2 )!!!

70 Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log 2 n) Worst case running time: O(n 2 )!!! What can we do to avoid worst case?

71 Analysis of Quicksort Best case: split in the middle — Θ(n log n) Worst case: sorted array! — Θ(n 2 ) Average case: random arrays — Θ(n log n) Improvements Improvements: better pivot selection: median of three partitioning switch to insertion sort on small subfiles elimination of recursion These combine to 20-25% improvement T(n) = T(n-1) + Θ(n)


Download ppt "Introduction to Algorithms Rabie A. Ramadan rabieramadan.org 4 Some of the sides are exported from different sources."

Similar presentations


Ads by Google