Download presentation
Presentation is loading. Please wait.
Published byGeoffrey Booth Modified over 9 years ago
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)
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.