0% found this document useful (0 votes)
70 views20 pages

Quicksort: By: Vimal Awasthi

Quicksort is a sorting algorithm that works by partitioning an array around a pivot value and recursively sorting the sub-partitions. It has best-case time complexity of O(n log n) when the partitions are balanced, and worst-case of O(n^2) when the array is already sorted. The key step is partitioning the array such that elements smaller than the pivot come before elements larger than the pivot. Choosing the pivot carefully, such as taking the median of three randomly selected elements, helps improve performance and reduces the chances of worst-case behavior.

Uploaded by

Pawan_Singh_6974
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
Download as ppt, pdf, or txt
0% found this document useful (0 votes)
70 views20 pages

Quicksort: By: Vimal Awasthi

Quicksort is a sorting algorithm that works by partitioning an array around a pivot value and recursively sorting the sub-partitions. It has best-case time complexity of O(n log n) when the partitions are balanced, and worst-case of O(n^2) when the array is already sorted. The key step is partitioning the array such that elements smaller than the pivot come before elements larger than the pivot. Choosing the pivot carefully, such as taking the median of three randomly selected elements, helps improve performance and reduces the chances of worst-case behavior.

Uploaded by

Pawan_Singh_6974
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1/ 20

Quicksort

By:
Vimal Awasthi
Quicksort I

• To sort a[left...right]:
1. if left < right:
1.1. Partition a[left...right] such that:
all a[left...p-1] are less than a[p], and
all a[p+1...right] are >= a[p]
1.2. Quicksort a[left...p-1]
1.3. Quicksort a[p+1...right]
2. Terminate

2
Partitioning (Quicksort II)
• A key step in the Quicksort algorithm is
partitioning the array
– We choose some (any) number p in the array to use as
a pivot
– We partition the array into three parts:

numbers p numbers greater


less than p than or equal to p

3
Partitioning II
• Choose an array value (say, the first) to use as the
pivot
• Starting from the left end, find the first element
that is greater than or equal to the pivot
• Searching backward from the right end, find the
first element that is less than the pivot
• Interchange (swap) these two elements
• Repeat, searching from where we left off, until
done

4
Partitioning

• To partition a[left...right]:
1. Set p = a[left], l = left + 1, r = right;
2. while l < r, do
2.1. while l < right & a[l] < p, set l = l + 1
2.2. while r > left & a[r] >= p, set r = r - 1
2.3. if l < r, swap a[l] and a[r]
3. Set a[left] = a[r], a[r] = p
4. Terminate

5
Example of partitioning

• choose pivot: 436924312189356


• search: 436924312189356
• swap: 433924312189656
• search: 433924312189656
• swap: 433124312989656
• search: 433124312989656
• swap: 433122314989656
• search: 433122314989656 (left > right)
• swap with pivot: 133122344989656
6
Partitioning in Java
static void partition(int[] a) {
int left = 0, right = a.length - 1;
int p = a[left], l = left + 1, r = right;
while (l < r) {
while (l < right && a[l] < p) l++;
while (r > left && a[r] >= p) r--;
if (l < r) {
int temp = a[l]; a[l] = a[r]; a[r] = temp;
}
}
a[left] = a[r];
a[r] = p;
}
7
Analysis of quicksort—best case
• Suppose each partition operation divides the array
almost exactly in half
• Then the depth of the recursion in log2n
– Because that’s how many times we can halve n
• However, there are many recursions!
– How can we figure this out?
– We note that
• Each partition is linear over its subarray
• All the partitions at one level cover the array

8
Partitioning at various levels

9
Best case II
• We cut the array size in half each time
• So the depth of the recursion in log2n
• At each level of the recursion, all the partitions at
that level do work that is linear in n
• O(log2n) * O(n) = O(n log2n)
• Hence in the average case, quicksort has time
complexity O(n log2n)
• What about the worst case?

10
Worst case
• In the worst case, partitioning always divides the
size n array into these three parts:
– A length one part, containing the pivot itself
– A length zero part, and
– A length n-1 part, containing everything else
• We don’t recur on the zero-length part
• Recurring on the length n-1 part requires (in the
worst case) recurring to depth n-1

11
Worst case partitioning

12
Worst case for quicksort
• In the worst case, recursion may be n levels deep
(for an array of size n)
• But the partitioning work done at each level is still
n
• O(n) * O(n) = O(n2)
• So worst case for Quicksort is O(n2)
• When does this happen?
– When the array is sorted to begin with!

13
Typical case for quicksort

• If the array is sorted to begin with, Quicksort is


terrible: O(n2)
• It is possible to construct other bad cases
• However, Quicksort is usually O(n log2n)
• The constants are so good that Quicksort is
generally the fastest algorithm known
• Most real-world sorting is done by Quicksort

14
Tweaking Quicksort

• Almost anything you can try to “improve”


Quicksort will actually slow it down
• One good tweak is to switch to a different
sorting method when the subarrays get small
(say, 10 or 12)
– Quicksort has too much overhead for small array
sizes
• For large arrays, it might be a good idea to check
beforehand if the array is already sorted
– But there is a better tweak than this
15
Picking a better pivot
• Before, we picked the first element of the subarray
to use as a pivot
– If the array is already sorted, this results in O(n2)
behavior
– It’s no better if we pick the last element
• We could do an optimal quicksort (guaranteed
O(n log n)) if we always picked a pivot value
that exactly cuts the array in half
– Such a value is called a median: half of the values in
the array are larger, half are smaller
– The easiest way to find the median is to sort the array
and pick the value in the middle (!)
16
Median of three
• Obviously, it doesn’t make sense to sort the array
in order to find the median to use as a pivot
• Instead, compare just three elements of our
(sub)array—the first, the last, and the middle
– Take the median (middle value) of these three as pivot
– It’s possible (but not easy) to construct cases which will
make this technique O(n2)
• Suppose we rearrange (sort) these three numbers
so that the smallest is in the first position, the
largest in the last position, and the other in the
middle
– This lets us simplify and speed up the partition loop
17
Simplifying the inner loop
• Here’s the heart of the partition method:
while (l < r) {
while (l < right && a[l] < p) l++;
while (r > left && a[r] >= p) r--;
if (l < r) {
int temp = a[l]; a[l] = a[r]; a[r] = temp;
}
}

• Because of the way we chose the pivot, we know that


a[leftEnd] <= pivot <= a[rightEnd]
• Therefore a[l] < p will happen before l < right
• Likewise, a[r] >= p will happen before r > left
• Therefore the tests l < right and r > left can be omitted
18
Final comments
• Quicksort is the fastest known sorting algorithm
• For optimum efficiency, the pivot must be chosen
carefully
• “Median of three” is a good technique for
choosing the pivot
• However, no matter what you do, there will be
some cases where Quicksort runs in O(n2) time

19
The End

20

You might also like