快速排序¶
采用分治法思想:
分解: 将数组A[p..r]划分成两个(也可能是空)的子数组A[p..q-1]和A[q+1..r],
使得左边数组中的元素都小于A[p],而右边数组元素都大于A[p]
解决: 通过递归调用快速排序,对子数组A[p..q-1]和A[q+1..r]进行排序
合并: 原址排序,不需要合并,数组已经排好序了
快速排序的优点:
最坏情况下时间复杂度为O(n^2),但是期望时间是O(nlg(n)),
而且O(nlg(n))隐含常数因子非常的小,而且还是原址排序,
所以实际中使用最多的排序算法就是快速排序
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
from random import randint
def quickSort(seq):
# __quickSubSort(seq, 0, len(seq) - 1)
__quickSubSortTail(seq, 0, len(seq) - 1)
def __partition(A, p, r):
"""分解子数组"""
x = A[r] # 取最后一个数作为 pivot
i = p - 1
for j in range(p, r):
if A[j] <= x:
i += 1
A[i], A[j] = A[j], A[i]
A[i + 1], A[r] = A[r], A[i + 1] # 把 pivot 放在正确的位置
return i + 1 # 返回 pivot 的下标
def __randPartition(A, p, r):
"""分解子数组: 随机化版本"""
rinx = randint(p, r) # 随机的 pivot
A[rinx], A[r] = A[r], A[rinx] # 还是将这个 pivot 放到最后
x = A[r]
i = p - 1
for j in range(p, r):
if A[j] <= x:
i += 1
A[i], A[j] = A[j], A[i]
A[i + 1], A[r] = A[r], A[i + 1]
return i + 1
def __quickSubSort(seq, p, r):
"""递归版本的"""
if p < r:
#q = __partition(seq, p, r)
q = __randPartition(seq, p, r)
__quickSubSort(seq, p, q - 1)
__quickSubSort(seq, q + 1, r)
def __quickSubSortTail(seq, p, r):
"""循环版本,模拟尾递归,可以大大减少递归栈深度,而且时间复杂度不变"""
while p < r:
#q = __partition(seq, p, r)
q = __randPartition(seq, p, r)
if q - p < r - q:
__quickSubSortTail(seq, p, q - 1)
p = q + 1
else:
__quickSubSortTail(seq, q + 1, r)
r = q - 1
if __name__ == '__main__':
seq = [9, 7, 8, 10, 16, 3, 14, 2, 1, 4]
quickSort(seq)
print(seq)