快速排序


快速排序的工作原理

1,從數組中選擇一個元素,這個元素被稱為基准值(pivot)。

2,接下來,找出比基准值小的元素以及比基准值大的元素。這被稱為分區(partitioning)。

現在有:

 一個由所有小於基准值的數字組成的子數組;
 基准值;
 一個由所有大於基准值的數組組成的子數組。

3, 對這兩個子數組進行快速排序。

4,兩個子數組里面的元素

O(n log n)

def quick_sort(list):
    if len(list) < 2: # 基准條件,遞歸的終止條件
        return list
    else:
        pivot = list[0] # 設立基准值
        less = [i for i in list[1:] if i <= pivot] #小於等於基准值的放到一個列表
        greater = [j for j in list[1:] if j>= pivot] #大於等於基准值的放到一個列表
        return quick_sort(less) + [pivot] + quick_sort(greater) # 返回的一個個小的列表相加

var = quick_sort([8,2,5,3,1])
print(var) # [1, 2, 3, 5, 8]

快排涉及到D&C (分而治之),遞歸調用棧原理。

 

快速排序的性能高度依賴於你選擇的基准值。假設你總是將第一個元素用作基准值,且要處
理的數組是有序的。由於快速排序算法不檢查輸入數組是否有序,因此它依然嘗試對其進行排序。

 

 

注意,數組並沒有被分成兩半,相反,其中一個子數組始終為空,這導致調用棧非常長。現
在假設你總是將中間的元素用作基准值,在這種情況下,調用棧如下。

 

調用棧短得多!因為你每次都將數組分成兩半,所以不需要那么多遞歸調用。你很快就到達
了基線條件,因此調用棧短得多。
第一個示例展示的是最糟情況,而第二個示例展示的是最佳情況。在最糟情況下,棧長為
O(n),而在最佳情況下,棧長為O(log n)。
現在來看看棧的第一層。你將一個元素用作基准值,並將其他的元素划分到兩個子數組中。
這涉及數組中的全部8個元素,因此該操作的時間為O(n)。在調用棧的第一層,涉及全部8個元素,
但實際上,在調用棧的每層都涉及O(n)個元素。

即便以不同的方式划分數組,每次也將涉及O(n)個元素。

在這個示例中,層數為O(log n)(用技術術語說,調用棧的高度為O(log n)),而每層需要的
時間為O(n)。因此整個算法需要的時間為O(n) * O(log n) = O(n log n)。這就是最佳情況。
在最糟情況下,有O(n)層,因此該算法的運行時間為O(n) * O(n) = O(n2)。
知道嗎?這里要告訴你的是,最佳情況也是平均情況。只要你每次都隨機地選擇一個數組元
素作為基准值,快速排序的平均運行時間就將為O(n log n)。快速排序是最快的排序算法之一,也
是D&C典范。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM