排序算法-快速排序
快速排序(选择升序排序)
- 思路
-
- 从序列中选择一个枢轴(支点,pivot),假设每次选择索引0位置为支点
-
- 利用支点将序列分割成两个子队列
小于支点的放在支点的左侧
大于支点的放在支点的右侧
等于支点的左右都可以(这里相等放右边)
- 利用支点将序列分割成两个子队列
-
- 对子序列进行1,2操作,直到不能再分割(也就是子序列只剩下1个元素)
-
class QuickSort {
var array = [5, 7, 2, 8, 9, 4, 7, 3, 2]
func sort() {
let begin = 0
let end = array.count
sort(begin: begin, end: end)
}
// 对 [begin, end) 元素快速排序
func sort(begin: Int, end: Int) {
if end - begin < 2 { return }
// 确定支点的位置
let pivot = pivotIndex(begin: begin, end: end)
// 对子序列进行快速排序
sort(begin: begin, end: pivot)
sort(begin: pivot + 1, end: end)
}
/// 构造 [begin, end) 范围的支点元素,返回支点元素的最终位置
private func pivotIndex(begin: Int, end: Int) -> Int {
var b = begin, e = end
// 备份 begin 位置的元素
let pivot = array[b]
// 右开区间,end - 1 指向最后一个元素
e -= 1
while b < e {
while b < e {
if pivot < array[e] { // 右边元素大
e -= 1
} else { // 右边 <= 支点,将元素放入左边,换方向遍历
array[b] = array[e]
b += 1
break
}
}
while b < e {
if pivot > array[b] { // 左边 < 支点
b += 1
} else { // 左边 >= 支点,将元素放入右边,换方向遍历
array[e] = array[b]
e -= 1
break
}
}
}
// 说明 begin == end,将支点元素放入最终位置
array[e] = pivot // 等价 array[begin] = pivot
// 返回支点元素的位置
return e
}
}
let qs = QuickSort()
qs.sort()
print(qs.array) // [2, 2, 3, 4, 5, 7, 7, 8, 9]
最好、平均时间复杂度: O(nlogn), 最坏时间复杂度: O(n^2)
空间复杂度:O(logn)
稳定性:不稳定排序