Python实现 《算法导论 第三版》中的算法 第7章 快速排序

目录

      • 第7章 快速排序
        • 1. 快速排序
        • 2. 多种写法总结

第7章 快速排序

1. 快速排序

快速排序是一种最坏情况时间复杂度为 Θ ( n 2 ) \Theta(n^2) Θ(n2)的排序算法。虽然最坏情况很差,但是快速排序通常是实际排序应用中最好的选择。因为它的平均性能非常好:期望时间复杂度为 Θ ( n l g n ) \Theta(nlgn) Θ(nlgn),而且其中隐含的常数因子非常小。另外,它还是原址排序,空间复杂度为 O ( 1 ) O(1) O(1)

下面实现了书中的伪代码和习题,包括:

  • P95:QUICKSORT,快速排序,初始调用为QUICKSORT(A, 0, A.length-1),见quick_sort
  • P95:PARTITION,快速排序中的数组划分,实现了对子数组A[p…r]的原址重排,见partition
  • P100:RANDOMIZED-PARTITIONRANDOMIZED-QUICKSORT,随机选取主元的划分和对应的快速排序,见randomized_partitionrandomized_quick_sort。因为主元元素是随机选取的,我们期望在平均情况下,对输入数组的划分是比较均衡的。
  • P103:思考题7-1,Hoare划分,见hoare_partitionhoare_quick_sort
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()  

2. 多种写法总结

个人认为填坑法比较好记,代码最短,条件最简单。

# 填坑法
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)

你可能感兴趣的:(默认,算法,Python)