0% found this document useful (0 votes)
65 views

L03 DivideConquer - Part02

Quicksort follows the divide and conquer paradigm. It divides the array into two subarrays by partitioning elements around a pivot value. It then recursively sorts the two subarrays. The partition step takes linear time O(n). In the worst case, the partition is highly unbalanced, leading to a recursion tree with height n and O(n^2) runtime. In the best case, each partition divides the problem size in half, leading to a balanced binary tree and O(nlogn) runtime. Most real-world inputs exhibit behavior closer to the average case.

Uploaded by

Enmusk
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
65 views

L03 DivideConquer - Part02

Quicksort follows the divide and conquer paradigm. It divides the array into two subarrays by partitioning elements around a pivot value. It then recursively sorts the two subarrays. The partition step takes linear time O(n). In the worst case, the partition is highly unbalanced, leading to a recursion tree with height n and O(n^2) runtime. In the best case, each partition divides the problem size in half, leading to a balanced binary tree and O(nlogn) runtime. Most real-world inputs exhibit behavior closer to the average case.

Uploaded by

Enmusk
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 17

Lecture 03

Divide and Conquer


CSE373: Design and Analysis of Algorithms
Quicksort

Follows the divide-and-conquer paradigm.


Divide: Partition (separate) the array A[p..r] into two (possibly
empty) subarrays A[p..q–1] and A[q+1..r].
Each element in A[p..q–1]  A[q].
A[q]  each element in A[q+1..r].
Index q is computed as part of the partitioning procedure.
Conquer: Sort the two subarrays by recursive calls to quicksort.

Combine: The subarrays are sorted in place – no work is


needed to combine them.
How do the divide and combine steps of quicksort compare
with those of merge sort?
Partitioning

Select the last element A[r] in the subarray A[p..r] as the


pivot – the element around which to partition.
As the procedure executes, the array is partitioned into
four (possibly empty) regions.
1. A[p..i] — All entries in this region are  pivot.
2. A[i+1..j – 1] — All entries in this region are > pivot.
3. A[r] = pivot.
4. A[j..r – 1] — Not known how they compare to pivot.
Partitioning
PARTITION(A, p, r)
1. x = A[r]
2. i = p-1
3. for j = p to r – 1
4. if A[j]  x
5. i=i+1
6. exchange A[i] with A[j]
7. exchange A[i + 1] with A[r] QUICKSORT(A, p, r)
8. return i + 1 1. if p < r then
A[p..r] 2. q = PARTITION(A, p, r);
3. QUICKSORT (A, p, q – 1);
5 4. QUICKSORT (A, q + 1, r)

A[p..q – 1] A[q+1..r]
Partition 5

5 5
Example

p r
initially: 2 5 8 3 9 4 1 7 10 6 note: pivot (x) = 6
i j

next iteration: 2 5 8 3 9 4 1 7 10 6
PARTITION(A, p, r)
i j 1. x = A[r]
2. i = p-1
next iteration: 2 5 8 3 9 4 1 7 10 6 3. for j = p to r – 1
i j 4. if A[j]  x
5. i=i+1
next iteration: 2 5 8 3 9 4 1 7 10 6 6. exchange A[i] with A[j]
7. exchange A[i + 1] with A[r]
i j 8. return i + 1

next iteration: 2 5 3 8 9 4 1 7 10 6
i j
Example (Continued)

next iteration: 2 5 3 8 9 4 1 7 10 6
i j
next iteration: 2 5 3 8 9 4 1 7 10 6
i j
next iteration: 2 5 3 4 9 8 1 7 10 6 PARTITION(A, p, r)
1. x = A[r]
i j 2. i = p-1
3. for j = p to r – 1
next iteration: 2 5 3 4 1 8 9 7 10 6 4. if A[j]  x
i j 5. i=i+1
6. exchange A[i] with A[j]
next iteration: 2 5 3 4 1 8 9 7 10 6 7. exchange A[i + 1] with A[r]
i j 8. return i + 1

next iteration: 2 5 3 4 1 8 9 7 10 6
i j
after final swap: 2 5 3 4 1 6 9 7 10 8
i j
Complexity of Partition
PartitionTime(n) is given by the number of iterations in the
for loop.
(n) : n = r – p + 1.

PARTITION(A, p, r)
1. x = A[r]
2. i = p-1
3. for j = p to r – 1
4. if A[j]  x
5. i=i+1
6. exchange A[i] with A[j]
7. exchange A[i + 1] with A[r]
8. return i + 1
Algorithm Performance
Running time of quicksort depends on whether the
partitioning is balanced or not.

Worst-Case Partitioning (Unbalanced Partitions):


Occurs when every call to partition results in the most
unbalanced partition.
Partition is most unbalanced when
Subproblem 1 is of size n – 1, and subproblem 2 is of size 0 or vice versa.
pivot  every element in A[p..r – 1] or pivot < every element in A[p..r – 1].
Every call to partition is most unbalanced when
Array A[1..n] is sorted or reverse sorted!
Worst-case of quicksort
Input sorted or reverse sorted.
Partition around min or max element.
One side of partition always has one element.
Worst-case recursion tree
Worst-case recursion tree
Worst-case recursion tree
Best-case Partitioning
Size of each subproblem  n/2.
One of the subproblems is of size n/2
The other is of size n/2 −1.
Recurrence for running time
T(n)  2T(n/2) + PartitionTime(n)
= 2T(n/2) + (n)
T(n) = (n lg n)
Recursion Tree for Best-case Partition

cn cn

cn/2 cn/2 cn

lg n

cn/4 cn/4 cn/4 cn/4 cn

c c c c c c cn
Total : O(n lg n)
Best-case analysis
Analysis of “almost-best” case
Analysis of “almost-best” case

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy