理解快速排序的分治问题
快速排序是一个分治算法,基本思路是在每次分治中对数组找到一个分治点,使得左边的元素都小于等于,右边的元素都大于。注意这里与二分的不同之处在于分治算法除了要找到分治点外,还需要对数组重组。
QuickSort(A, l, r):
if l < r :
p = Partition(A, l, r)
QuickSort(A, l, p - 1)
QuickSort(A, p + 1, r)
Lomuto Partition切分算法描述如下。
注意: Lomuto Partition并不是最优的实现
将数组划分为四个部分,每个部分和目标值的大小关系不同,其中:

初始条件为,此时都为空,循环不变量成立。
终结条件为,此时即为我们要寻找的分治点。
当时,有两种情况:
- ,此时对 ,不变量成立
- ,此时交换,。即把放到小于的区间末尾,并将此区间右移一位,保持循环不变量成立

按照四要素对Partition编码并实现快排。
注意:对下标的处理
func swap(A []int, i, j int) {
tmp := A[i]
A[i] = A[j]
A[j] = tmp
}
func Partition(A []int, l, r int) (pivot int) {
i := l
j := l
x := A[r-1]
for j < r {
if A[j] <= x {
swap(A, i, j)
i = i + 1
}
j = j + 1
}
return i - 1
}
func QSort(A []int, l, r int) {
if l < r {
pivot := Partition(A, l, r)
QSort(A, l, pivot)
QSort(A, pivot+1, r)
}
}
分治点是一个有用的元素,由于它“中间点”的性质,也可以用来找第k大(小)的元素。
func KthElement(A []int, l, r, k int) int {
if l < r {
pivot := Partition(A, l, r)
ki := k - 1
if ki == pivot {
return A[pivot]
} else if ki < pivot {
return KthElement(A, l, pivot, k)
} else {
return KthElement(A, pivot+1, r, k)
}
}
return -1
}