1. 程式人生 > >雙路快排

雙路快排

序列元素重複,是序列已經排好序的一種特殊情況,如果一個序列中的元素全部相同,也將出現最差情況。
如果序列中存在大量重複元素,在普通快排中,相等的元素會被全部放到分割槽點的一邊,這樣會大大增加快排的時間複雜度,雙路快排就是用來解決這個問題的。
能夠將序列均衡分開的分割槽點才是好的分割槽點。均勻分開意味著保持O(logn)的複雜度。

from random import shuffle, randrange

def quick_sort(lst, left, right):
    # 當只有一個元素的時候退出遞迴
    if left < right:
        p = partition(lst, left, right)
        # 左右分割槽分別遞迴
        quick_sort(lst, left, p)
        quick_sort(lst, p+1, right)

def partition(lst, left, right):
    rand = randrange(left, right)
    lst[left], lst[rand] = lst[rand], lst[left]   # 隨機挑選出一個元素,與第一個元素交換,作為分割槽點
    pivot = lst[left]    # 以第一個元素為分割槽點
    leftpos = left + 1
    rightpos = right - 1
    while leftpos <= rightpos:
        while leftpos <= rightpos and lst[leftpos] <= pivot:
            leftpos += 1
        while leftpos <= rightpos and lst[rightpos] >= pivot:
            rightpos -= 1
        if leftpos > rightpos:
            break
        lst[leftpos], lst[rightpos] = lst[rightpos], lst[leftpos]
    # 將pivot放入分割槽點
    lst[leftpos-1], lst[left] = lst[left], lst[leftpos-1]
    # 返回分割槽點索引
    return leftpos-1


source = list(range(10))
shuffle(source)
print(source)

quick_sort(source, 0, len(source))
print(source)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]