算法导论7-1
读书笔记
本小节介绍了大名鼎鼎的快速排序,快速排序在最坏的情况下的时间复杂度为\(\theta(n^2)\);在元素互异的情况下,期望时间复杂度为\(O(n\lg{n})\)。快速排序使用了分治思想,分治过程如下:
分解
数组\(A[p..r]\)被划分为两个(可能为空)的子数组\(A[p..q-1]\)和\(A[q+1..r]\),是的\(A[p..q-1]\)中的每个元素都小于等于\(A[q]\),而\(A[q]\)也小于等于\(A[q+1..r]\)中的每个元素。其中,计算下标\(q\)也是划分过程的一部分。
解决
通过递归调用快速排序,对子数组\(A[p..q-1]\)和\(A[q+1..r]\)进行排序。
合并
因为子数组都是原址排序的,所以不需要合并操作:数组\(A[p..r]\)已经有序。
在别的关于快速排序的说明中,有着基准值这一概念,此处的基准值直接选定了子数组的最后一个元素。
伪代码
QUICKSORT(A, p, r)
if p < r
q = PARTITION(A, p, r)
QUICKSORT(A, p, q - 1)
QUICKSORT(A, q + 1, r)
PARTITION(A, p, r)
x = A[r]
i = p - 1
for j = p to r - 1
if A[j] <= x
i = i + 1
exchange A[i] with A[j]
exchange A[i+1] with A[r]
return i + 1
在上述伪代码中变量\(i\)用于存储左右两个子数组的分界点的坐标。
课后习题
7.1-1
参照图7-1的方法,说明\(PARTITION\)在数组\(A=<13, 19, 9, 5,12,8,7,4,21,2,6,11>\)上的操作过程。
略
7.1-2
当数组\(A[p..r]\)中的元素都相同时,\(PARTITION\)返回的\(q\)值是什么?修改\(PARTITION\),使得当数组\(A[p..r]\)中的所有元素都相同时,\(q=\lfloor (p+r)/2 \rfloor\)。
第一小问,\(q=r\);
第二小问:
PARTITION(A, p, r)
x = A[(p+r)/2]
i = p - 1
for j = p to r - 1
if A[j] <= x
i = i + 1
exchange A[i] with A[j]
exchange A[i+1] with A[r]
return i + 1
7.1-3
请简要地证明:在规模为\(n\)的子数组上,\(PARTITION\)的时间复杂度为\(\theta(n)\)。
这是显而易见的,对一个无序的数组划分左右子数组,一定需要逐个比较,所以时间复杂度为\(\theta(n)\)。
7.1-4
如何修改\(QUICKSORT\),使得它能够以降序进行排序?
QUICKSORT(A, p, r)
if p < r
q = PARTITION(A, p, r)
QUICKSORT(A, p, q - 1)
QUICKSORT(A, q + 1, r)
PARTITION(A, p, r)
x = A[r]
i = p - 1
for j = p to r - 1
if A[j] >= x
i = i + 1
exchange A[i] with A[j]
exchange A[i+1] with A[r]
return i + 1