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

7.1 Description of Quicksort

The quicksort algorithm uses a divide-and-conquer approach to sort arrays. It works by partitioning the array around a pivot element, and then recursively sorting the subarrays. The key partitioning step rearranges the array such that elements less than the pivot come before elements greater than the pivot. While quicksort has a worst-case running time of O(n^2), its expected running time is O(n log n) which makes it an efficient choice in practice. The document goes on to describe the quicksort algorithm and partitioning process in more detail.
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)
55 views5 pages

7.1 Description of Quicksort

The quicksort algorithm uses a divide-and-conquer approach to sort arrays. It works by partitioning the array around a pivot element, and then recursively sorting the subarrays. The key partitioning step rearranges the array such that elements less than the pivot come before elements greater than the pivot. While quicksort has a worst-case running time of O(n^2), its expected running time is O(n log n) which makes it an efficient choice in practice. The document goes on to describe the quicksort algorithm and partitioning process in more detail.
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 .n2 / on an input array
of n numbers. Despite this slow worst-case running time, quicksort is often the best
practical choice for sorting because it is remarkably efficient on the average: its
expected running time is .n lg n/, and the constant factors hidden in the .n lg n/
notation are quite small. It also has the advantage of sorting in place (see page 17),
and it works well even in virtual-memory environments.
Section 7.1 describes the algorithm and an important subroutine used by quicksort for partitioning. Because the behavior of quicksort is complex, we start with
an intuitive discussion of its performance in Section 7.2 and postpone its precise
analysis to the end of the chapter. Section 7.3 presents a version of quicksort that
uses random sampling. This algorithm has a good expected running time, and no
particular input elicits its worst-case behavior. Section 7.4 analyzes the randomized algorithm, showing that it runs in .n2 / time in the worst case and, assuming
distinct elements, in expected O.n lg n/ time.

7.1

Description of quicksort
Quicksort, like merge sort, applies the divide-and-conquer paradigm introduced
in Section 2.3.1. Here is the three-step divide-and-conquer process for sorting a
typical subarray Ap : : r!:
Divide: Partition (rearrange) the array Ap : : r! into two (possibly empty) subarrays Ap : : q ! 1! and Aq C 1 : : r! such that each element of Ap : : q ! 1! is
less than or equal to Aq!, which is, in turn, less than or equal to each element
of Aq C 1 : : r!. Compute the index q as part of this partitioning procedure.

Conquer: Sort the two subarrays Ap : : q ! 1! and Aq C 1 : : r! by recursive calls


to quicksort.

7.1 Description of quicksort

171

Combine: Because the subarrays are already sorted, no work is needed to combine
them: the entire array Ap : : r! is now sorted.
The following procedure implements quicksort:
Q UICKSORT .A; p; r/
1 if p < r
2
q D PARTITION .A; p; r/
3
Q UICKSORT .A; p; q ! 1/
4
Q UICKSORT .A; q C 1; r/
To sort an entire array A, the initial call is Q UICKSORT .A; 1; A:length/.
Partitioning the array
The key to the algorithm is the PARTITION procedure, which rearranges the subarray Ap : : r! in place.
PARTITION .A; p; r/
1 x D Ar!
2 i D p!1
3 for j D p to r ! 1
4
if Aj ! " x
5
i D i C1
6
exchange Ai! with Aj !
7 exchange Ai C 1! with Ar!
8 return i C 1
Figure 7.1 shows how PARTITION works on an 8-element array. PARTITION
always selects an element x D Ar! as a pivot element around which to partition the
subarray Ap : : r!. As the procedure runs, it partitions the array into four (possibly
empty) regions. At the start of each iteration of the for loop in lines 36, the regions
satisfy certain properties, shown in Figure 7.2. We state these properties as a loop
invariant:
At the beginning of each iteration of the loop of lines 36, for any array
index k,
1. If p " k " i, then Ak! " x.
2. If i C 1 " k " j ! 1, then Ak! > x.
3. If k D r, then Ak! D x.

172

Chapter 7 Quicksort

(a)

i p,j
2 8

r
4

(b)

p,i j
2 8

r
4

(c)

p,i
2 8

j
7

r
4

(d)

p,i
2 8

j
1

r
4

(e)

p
2

i
1

j
3

r
4

(f)

p
2

i
3

j
5

r
4

(g)

p
2

i
3

j
6

r
4

(h)

p
2

i
3

r
4

(i)

p
2

i
3

r
8

Figure 7.1 The operation of PARTITION on a sample array. Array entry Ar! becomes the pivot
element x. Lightly shaded array elements are all in the first partition with values no greater than x.
Heavily shaded elements are in the second partition with values greater than x. The unshaded elements have not yet been put in one of the first two partitions, and the final white element is the
pivot x. (a) The initial array and variable settings. None of the elements have been placed in either
of the first two partitions. (b) The value 2 is swapped with itself and put in the partition of smaller
values. (c)(d) The values 8 and 7 are added to the partition of larger values. (e) The values 1 and 8
are swapped, and the smaller partition grows. (f) The values 3 and 7 are swapped, and the smaller
partition grows. (g)(h) The larger partition grows to include 5 and 6, and the loop terminates. (i) In
lines 78, the pivot element is swapped so that it lies between the two partitions.

The indices between j and r ! 1 are not covered by any of the three cases, and the
values in these entries have no particular relationship to the pivot x.
We need to show that this loop invariant is true prior to the first iteration, that
each iteration of the loop maintains the invariant, and that the invariant provides a
useful property to show correctness when the loop terminates.

7.1 Description of quicksort

i
x

173

j
>x

r
x
unrestricted

Figure 7.2 The four regions maintained by the procedure PARTITION on a subarray Ap : : r!. The
values in Ap : : i! are all less than or equal to x, the values in Ai C 1 : : j ! 1! are all greater than x,
and Ar! D x. The subarray Aj : : r ! 1! can take on any values.

Initialization: Prior to the first iteration of the loop, i D p ! 1 and j D p. Because no values lie between p and i and no values lie between i C 1 and j ! 1,
the first two conditions of the loop invariant are trivially satisfied. The assignment in line 1 satisfies 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 Aj ! > x;
the only action in the loop is to increment j . After j is incremented, condition 2
holds for Aj ! 1! and all other entries remain unchanged. Figure 7.3(b) shows
what happens when Aj ! " x; the loop increments i, swaps Ai! and Aj !,
and then increments j . Because of the swap, we now have that Ai! " x, and
condition 1 is satisfied. Similarly, we also have that Aj ! 1! > x, since the
item that was swapped into Aj ! 1! is, by the loop invariant, greater than x.

Termination: At termination, j D r. Therefore, every entry in the array is in one


of the three sets described by the invariant, and we have partitioned the values
in the array into three sets: those less than or equal to x, those greater than x,
and a singleton set containing x.
The final two lines of PARTITION finish up by swapping the pivot element with
the leftmost element greater than x, thereby moving the pivot into its correct place
in the partitioned array, and then returning the pivots new index. The output of
PARTITION now satisfies the specifications given for the divide step. In fact, it
satisfies a slightly stronger condition: after line 2 of Q UICKSORT, Aq! is strictly
less than every element of Aq C 1 : : r!.
The running time of PARTITION on the subarray Ap : : r! is .n/, where
n D r ! p C 1 (see Exercise 7.1-3).
Exercises
7.1-1
Using Figure 7.1 as a model, illustrate the operation of PARTITION on the array
A D h13; 19; 9; 5; 12; 8; 7; 4; 21; 2; 6; 11i.

174

Chapter 7 Quicksort

(a)

j
>x
>x

x
p

(b)

j
x

r
x

>x

x
p

r
x

>x

x
p

r
x

i
x

r
x

>x

Figure 7.3 The two cases for one iteration of procedure PARTITION. (a) If Aj ! > x, the only
action is to increment j , which maintains the loop invariant. (b) If Aj ! ! x, index i is incremented,
Ai! and Aj ! are swapped, and then j is incremented. Again, the loop invariant is maintained.

7.1-2
What value of q does PARTITION return when all elements in the array Ap : : r!
have the same value? Modify PARTITION so that q D b.p C r/=2c when all
elements in the array Ap : : r! have the same value.
7.1-3
Give a brief argument that the running time of PARTITION on a subarray of size n
is .n/.
7.1-4
How would you modify Q UICKSORT to sort into nonincreasing order?

7.2

Performance of quicksort
The running time of quicksort depends on whether the partitioning is balanced or
unbalanced, which in turn depends on which elements are used for partitioning.
If the partitioning is balanced, the algorithm runs asymptotically as fast as merge

You might also like