0% found this document useful (0 votes)
12 views5 pages

Quicksort

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)
12 views5 pages

Quicksort

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/ 5

7 Quicksort

The quicksort algorithm has a worst-case running time of on an input array


of numbers. Despite this slow worst-case running time, quicksort is often the
best practical choice for sorting because it is remarkably efûcient on average: its
expected running time is lg when all numbers are distinct, and the constant
factors hidden in the lg notation are small. Unlike merge sort, it also has
the advantage of sorting in place (see page 158), and it works well even in virtual-
memory environments.
Our study of quicksort is broken into four sections. Section 7.1 describes the
algorithm and an important subroutine used by quicksort for partitioning. Because
the behavior of quicksort is complex, we’ll start with an intuitive discussion of
its performance in Section 7.2 and analyze it precisely at the end of the chapter.
Section 7.3 presents a randomized version of quicksort. When all elements are
distinct,1 this randomized algorithm has a good expected running time and no par-
ticular input elicits its worst-case behavior. (See Problem 7-2 for the case in which
elements may be equal.) Section 7.4 analyzes the randomized algorithm, showing
that it runs in time in the worst case and, assuming distinct elements, in
expected lg time.

You can enforce the assumption that the values in an array are distinct at the cost of
additional space and only constant overhead in running time by converting each input value to
an ordered pair with if or if and .
There are also more practical variants of quicksort that work well when elements are not distinct.
7.1 Description of quicksort 183

7.1 Description of quicksort

Quicksort, like merge sort, applies the divide-and-conquer method introduced in


Section 2.3.1. Here is the three-step divide-and-conquer process for sorting a sub-
array :
Divide by partitioning (rearranging) the array into two (possibly empty)
subarrays (the low side) and (the high side) such
that each element in the low side of the partition is less than or equal to the
pivot , which is, in turn, less than or equal to each element in the high side.
Compute the index of the pivot as part of this partitioning procedure.
Conquer by calling quicksort recursively to sort each of the subarrays
and .
Combine by doing nothing: because the two subarrays are already sorted, no work
is needed to combine them. All elements in are sorted and less than
or equal to , and all elements in are sorted and greater than or
equal to the pivot . The entire subarray cannot help but be sorted!
The Q UICKSORT procedure implements quicksort. To sort an entire -element
array , the initial call is Q UICKSORT .

Q UICKSORT
1 if
2 // Partition the subarray around the pivot, which ends up in .
3 PARTITION
4 Q UICKSORT // recursively sort the low side
5 Q UICKSORT // recursively sort the high side

Partitioning the array


The key to the algorithm is the PARTITION procedure on the next page, which
rearranges the subarray in place, returning the index of the dividing point
between the two sides of the partition.
Figure 7.1 shows how PARTITION works on an -element array. PARTITION
always selects the element as the pivot. As the procedure runs, each
element falls into exactly one of four regions, some of which may be empty. At
the start of each iteration of the for loop in lines 336, the regions satisfy certain
properties, shown in Figure 7.2. We state these properties as a loop invariant:
184 Chapter 7 Quicksort

PARTITION
1 // the pivot
2 // highest index into the low side
3 for to // process each element other than the pivot
4 if // does this element belong on the low side?
5 // index of a new slot in the low side
6 exchange with // put this element there
7 exchange with // pivot goes just to the right of the low side
8 return // new index of the pivot

At the beginning of each iteration of the loop of lines 336, for any array
index , the following conditions hold:
1. if , then (the tan region of Figure 7.2);
2. if , then (the blue region);
3. if , then (the yellow region).

We need to show that this loop invariant is true prior to the ûrst iteration, that
each iteration of the loop maintains the invariant, that the loop terminates, and that
correctness follows from the invariant when the loop terminates.
Initialization: Prior to the ûrst iteration of the loop, we have and
. Because no values lie between and and no values lie between
and , the ûrst two conditions of the loop invariant are trivially satisûed.
The assignment in line 1 satisûes the third condition.
Maintenance: As Figure 7.3 shows, we consider two cases, depending on the
outcome of the test in line 4. Figure 7.3(a) shows what happens when :
the only action in the loop is to increment . After has been incremented, the
second condition holds for and all other entries remain unchanged.
Figure 7.3(b) shows what happens when : the loop increments ,
swaps and , and then increments . Because of the swap, we now
have that , and condition is satisûed. Similarly, we also have that
, since the item that was swapped into is, by the loop
invariant, greater than .
Termination: Since the loop makes exactly iterations, it terminates, where-
upon . At that point, the unexamined subarray is empty, and
every entry in the array belongs to one of the other three sets described by the
invariant. Thus, the values in the array have been partitioned into three sets:
those less than or equal to (the low side), those greater than (the high side),
and a singleton set containing (the pivot).
7.1 Description of quicksort 185

i p,j r
(a) 2 8 7 1 3 5 6 4

p,i j r
(b) 2 8 7 1 3 5 6 4

p,i j r
(c) 2 8 7 1 3 5 6 4

p,i j r
(d) 2 8 7 1 3 5 6 4

p i j r
(e) 2 1 7 8 3 5 6 4

p i j r
(f) 2 1 3 8 7 5 6 4

p i j r
(g) 2 1 3 8 7 5 6 4

p i r
(h) 2 1 3 8 7 5 6 4

p i r
(i) 2 1 3 4 7 5 6 8

Figure 7.1 The operation of PARTITION on a sample array. Array entry becomes the pivot
element . Tan array elements all belong to the low side of the partition, with values at most .
Blue elements belong to the high side, with values greater than . White elements have not yet been
put into either side of the partition, and the yellow element is the pivot . (a) The initial array and
variable settings. None of the elements have been placed into either side of the partition. (b) The
value is <swapped with itself= and put into the low side. (c)–(d) The values and are placed into
to high side. (e) The values and are swapped, and the low side grows. (f) The values and are
swapped, and the low side grows. (g)–(h) The high side of the partition grows to include and ,
and the loop terminates. (i) Line 7 swaps the pivot element so that it lies between the two sides of
the partition, and line 8 returns the pivot’s new index.

The ûnal two lines of PARTITION ûnish up by swapping the pivot with the left-
most element greater than , thereby moving the pivot into its correct place in
the partitioned array, and then returning the pivot’s new index. The output of
PARTITION now satisûes the speciûcations given for the divide step. In fact, it
satisûes a slightly stronger condition: after line 3 of Q UICKSORT, is strictly
less than every element of .
186 Chapter 7 Quicksort

p i j r
x

≤x >x unknown

Figure 7.2 The four regions maintained by the procedure P ARTITION on a subarray . The
tan values in are all less than or equal to , the blue values in are all greater
than , the white values in have unknown relationships to , and .

p i j r
(a) >x x

≤x >x

p i j r
x

≤x >x

p i j r
(b) ≤x x

≤x >x

p i j r
x

≤x >x

Figure 7.3 The two cases for one iteration of procedure P ARTITION . (a) If , the only
action is to increment , which maintains the loop invariant. (b) If , index is incremented,
and are swapped, and then is incremented. Again, the loop invariant is maintained.

Exercise 7.1-3 asks you to show that the running time of PARTITION on a sub-
array of elements is .

Exercises

7.1-1
Using Figure 7.1 as a model, illustrate the operation of PARTITION on the array
.

You might also like