快速排序是一种最坏情况时间复杂度为 Θ ( n 2 ) \Theta(n^2) Θ(n2)的排序算法。虽然最坏情况很差,但是快速排序通常是实际排序应用中最好的选择。因为它的平均性能非常好:期望时间复杂度为 Θ ( n l g n ) \Theta(nlgn) Θ(nlgn),而且其中隐含的常数因子非常小。另外,它还是原址排序,空间复杂度为 O ( 1 ) O(1) O(1)。
下面实现了书中的伪代码和习题,包括:
def quick_sort(A, p, r):
if p < r:
q = partition(A, p, r)
quick_sort(A, p, q-1)
quick_sort(A, q+1, r)
def partition(A, p, r):
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 randomized_partition(A, p, r):
import random
i = random.randint(p, r)
A[i], A[r] = A[r], A[i]
return partition(A, p, r)
def randomized_quick_sort(A, p, r):
if p < r:
q = randomized_partition(A, p, r)
randomized_quick_sort(A, p, q-1)
randomized_quick_sort(A, q+1, r)
def hoare_partition(A, p, r):
x = A[p]
i = p
j = r
while True:
while j > i and A[j] >= x:
j -= 1
while i < j and A[i] <= x:
i += 1
if i < j:
A[i], A[j] = A[j], A[i]
else:
A[p] = A[j] #书上的伪代码有问题 缺少这两步
A[j] = x
return j
def hoare_quick_sort(A, p, r):
if p < r:
q = hoare_partition(A, p, r)
hoare_quick_sort(A, p, q-1)
hoare_quick_sort(A, q+1, r)
def test():
A = [2, 8, 7, 1, 3, 5, 6, 4] # P96例子
quick_sort(A, 0, len(A)-1)
print(A)
A = [2, 8, 7, 1, 3, 5, 6, 4]
randomized_quick_sort(A, 0, len(A)-1)
print(A)
A = [13, 19, 9, 5, 12, 8, 7, 4, 11, 2, 6, 21] # P103思考题7-1
hoare_quick_sort(A, 0, len(A)-1)
print(A)
if __name__ == '__main__':
test()
个人认为填坑法比较好记,代码最短,条件最简单。
# 填坑法
def partition1(A, left, right):
pivot = A[left]
while left < right:
while left < right and A[right] >= pivot:
right -= 1
A[left] = A[right]
while left < right and A[left] < pivot:
left += 1
A[right] = A[left]
A[left] = pivot
return left
# 交换法
def partition2(A, left, right):
pivot_idx = left
pivot = A[pivot_idx]
while left < right:
while left < right and A[right] >= pivot:
right -= 1
while left < right and A[left] <= pivot:
left += 1
if left < right:
A[left], A[right] = A[right], A[left]
A[pivot_idx], A[left] = A[left], A[pivot_idx]
# print(pivot_idx, A, left, right)
return left
# 顺序遍历法,算法导论中的写法
def partition3(A, left, right):
pivot = A[right]
store_idx = left
for cur in range(left, right):
if A[cur] < pivot:
A[store_idx], A[cur] = A[cur], A[store_idx]
store_idx += 1
A[store_idx], A[right] = A[right], A[store_idx]
return store_idx
def quick_sort(A, left, right):
if left < right:
p = partition1(A, left, right)
quick_sort(A, left, p - 1)
quick_sort(A, p + 1, right)
if __name__ == '__main__':
A = [0, 1, 2, 3, 4, 9, 8, 7, 4, 4]
quick_sort(A, 0, len(A)-1)
print(A)