雙路快排

序列元素重複,是序列已經排好序的一種特殊狀況,若是一個序列中的元素所有相同,也將出現最差狀況。
若是序列中存在大量重複元素,在普通快排中,相等的元素會被所有放到分區點的一邊,這樣會大大增長快排的時間複雜度,雙路快排就是用來解決這個問題的。
可以將序列均衡分開的分區點纔是好的分區點。均勻分開意味着保持O(logn)的複雜度。dom

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]
相關文章
相關標籤/搜索