快速排序:Python语言实现
什么是快速排序?
快速排序是一种常用的排序算法,比选择排序快得多。例如,C语言标准库中的函数qsort 实现的就是快速排序。像归并排序(merge sort)一样,快速排序也是一种分治的递归算法。
快速排序算法的步骤和说明
将数组SSS排序的基本算法由下列简单的四步组成:
- 如果SSS中的元素个数是000和111,则返回。
- 取SSS中任一元素vvv,称之为枢纽元(pivot)。
- 将S−{v}S - \{v\}S−{v}(即S中其余元素)划分成两个不相交的集合:S1={x∈S−{v}∣x≤v}S_{1} = \{ x \in S - \{v\} | x \le v \}S1={x∈S−{v}∣x≤v},S2={x∈S−{v}∣x≥v}S_{2} = \{ x \in S - \{v\} | x \ge v \}S2={x∈S−{v}∣x≥v}。
- 返回{quicksort(S1),后跟v,继而再quicksort(S2)}\{quicksort(S_{1}),后跟v,继而再quicksort(S_{2})\}{quicksort(S1),后跟v,继而再quicksort(S2)}。
下图给出快速排序算法的直观说明:
快速排序算法的伪码和说明
下面是对一个典型的子数组A[l…r]A[l…r]A[l…r]进行快速排序的伪代码:
QuickSort(A, l, r)
1 if l >= r
2 return
3 i = Partition(A, l, r)
4 QuickSort(A, l, i - 1)
5 QuickSort(A, i + 1, r)
而算法的核心是Partition过程:
Partition(A, l, r)
1 p = A[r]
2 i = l - 1
3 for j = l to r - 1
4 if A[j] <= p
5 i = i + 1
6 exchange A[i] with A[j]
7 exchange A[i + 1] with A[r]
8 return i + 1
下图显示了Partition如何在一个包含8个元素的数组上进行操作的过程。
Partition总是选择一个p=A[r]p = A[r]p=A[r]作为枢纽元(pivot),并围绕它来划分子数组A[l…r]A[l…r]A[l…r]。 随着程序的执行,数组被划分成4个(可能有空的)区域。 在Partition伪码的第3~6行的for循环的每一轮迭代的开始,每一个区域都满足一定的性质, 我们将这些性质作为循环不变量:
在第3~6行循环体的每一轮迭代开始时,对于任意数组下标kkk,有:
- 若l≤k≤il \le k \le il≤k≤i,则A[k]≤pA[k] \le pA[k]≤p。
- 若i+1≤k≤j−1i+1 \le k \le j-1i+1≤k≤j−1,则A[k]>pA[k] > pA[k]>p。
- 若k=rk = rk=r,则A[k]=pA[k] = pA[k]=p。
但是上述三种情况没有覆盖下标jjj到r−1r-1r−1,对应位置的值与枢纽元之间也不存在特定的大小关系。 如下图所示:
下图给出第3~6行循环体的每一轮迭代中,根据第4行中条件判断的不同结果,算法的不同处理。
快速排序算法的Python实现
基于快速排序算法的伪码,我们可以轻松的给出Python版本的实现。
首先是给出测试驱动代码:
test_quicksort.py
#!/usr/bin/env python3
# test_quicksort.py
from quicksort import quicksort
import random
def main(s