Python一行代碼實現快速排序

上期文章排序算法——(2)Python實現十大經常使用排序算法爲你們介紹了十大經常使用排序算法的前五種(冒泡、選擇、插入、希爾、歸併),由於快速排序的重要性,因此今天將單獨爲你們介紹一下快速排序!html

1、算法介紹

排序算法(Sorting algorithm)是計算機科學最古老、最基本的課題之一。要想成爲合格的程序員,就必須理解和掌握各類排序算法。其中"快速排序"(Quicksort)使用得最普遍,速度也較快。它是圖靈獎得主C. A. R. Hoare(託尼·霍爾)於1960時提出來的。
在這裏插入圖片描述python

2、算法原理

快排的實現方式多種多樣,豬哥給你們寫一種容易理解的:分治+迭代,只須要三步:程序員

  1. 在數列之中,選擇一個元素做爲"基準"(pivot),或者叫比較值。
  2. 數列中全部元素都和這個基準值進行比較,若是比基準值小就移到基準值的左邊,若是比基準值大就移到基準值的右邊
  3. 以基準值左右兩邊的子列做爲新數列,不斷重複第一步和第二步,直到全部子集只剩下一個元素爲止。

舉個例子,假設我如今有一個數列須要使用快排來排序:{3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48},咱們來看看使用快排的詳細步驟:面試

  1. 選取中間的26做爲基準值(基準值能夠隨便選)
  2. 數列從第一個元素3開始和基準值26進行比較,小於基準值,那麼將它放入左邊的分區中,第二個元素44比基準值26大,把它放入右邊的分區中,依次類推就獲得下圖中的第二列。
  3. 而後依次對左右兩個分區進行再分區,獲得下圖中的第三列,依次往下,直到最後只有一個元素
  4. 分解完成再一層一層返回,返回規則是:左邊分區+基準值+右邊分區

在這裏插入圖片描述

3、代碼實現

quick_sort = lambda array: array if len(array) <= 1 else quick_sort([item for item in array[1:] if item <= array[0]]) + [array[0]] + quick_sort([item for item in array[1:] if item > array[0]])

是否是很簡潔很秀,若是再有面試官讓你手寫一個快排,你就把這行寫上去吧,面試官見了都要喊你秀兒,哈哈。算法

在你感嘆python吊炸天的同時,你因該考慮到代碼的可讀性問題,lambda函數設計是爲了代碼的簡潔性,可是濫用的話會致使可讀性變得極差,並且如今pep8代碼規範中也不建議使用lambda函數了,建議使用關鍵字def去定義一個函數,因此下面豬哥給你們寫一段符合pythonic風格的快排代碼數組

def quick_sort(arr):
    """快速排序"""
    if len(arr) < 2:
        return arr
    # 選取基準,隨便選哪一個均可以,選中間的便於理解
    mid = arr[len(arr) // 2]
    # 定義基準值左右兩個數列
    left, right = [], []
    # 從原始數組中移除基準值
    arr.remove(mid)
    for item in arr:
        # 大於基準值放右邊
        if item >= mid:
            right.append(item)
        else:
            # 小於基準值放左邊
            left.append(item)
    # 使用迭代進行比較
    return quick_sort(left) + [mid] + quick_sort(right)

4、算法分析

  1. 穩定性:快排是一種不穩定排序,好比基準值的先後都存在與基準值相同的元素,那麼相同值就會被放在一邊,這樣就打亂了以前的相對順序
  2. 比較性:由於排序時元素之間須要比較,因此是比較排序
  3. 時間複雜度:快排的時間複雜度爲O(nlogn)
  4. 空間複雜度:排序時須要另外申請空間,而且隨着數列規模增大而增大,其複雜度爲:O(nlogn)
  5. 歸併排序與快排 :歸併排序與快排兩種排序思想都是分而治之,可是它們分解和合並的策略不同:歸併是從中間直接將數列分紅兩個,而快排是比較後將小的放左邊大的放右邊,因此在合併的時候歸併排序仍是須要將兩個數列從新再次排序,而快排則是直接合並再也不須要排序,因此快排比歸併排序更高效一些,能夠從示意圖中比較兩者之間的區別。
    在這裏插入圖片描述

5、快排優化

快速排序有一個缺點就是對於小規模的數據集性能不是很好。可能有人認爲能夠忽略這個缺點不計,由於大多數排序都只要考慮大規模的適應性就好了。可是快速排序算法使用了分治技術,最終來講大的數據集都要分爲小的數據集來進行處理,因此快排分解到最後幾層性能不是很好,因此咱們就可使用揚長避短的策略去優化快排:app

  1. 先使用快排對數據集進行排序,此時的數據集已經達到了基本有序的狀態
  2. 而後當分區的規模達到必定小時,便中止快速排序算法,而是改用插入排序,由於咱們以前講過插入排序在對基本有序的數據集排序有着接近線性的複雜度,性能比較好。

這一改進被證實比持續使用快速排序算法要有效的多。函數

6、模擬面試

  • 面試官:你瞭解快排嗎?
  • 你:略知一二
  • 面試官:那你講講快排的算法思想吧
  • 你:快排基本思想是:從數據集中選取一個基準,而後讓數據集的每一個元素和基準值比較,小於基準值的元素放入左邊分區大於基準值的元素放入右邊分區,最後以左右兩邊分區爲新的數據集進行遞歸分區,直到只剩一個元素。
  • 面試官:快排有什麼優勢,有什麼缺點?
  • 你:分治思想的排序在處理大數據集量時效果比較好,小數據集性能差些。
  • 面試官:那該如何優化?
  • 你:對大規模數據集進行快排,當分區的規模達到必定小時改用插入排序,插入排序在小數據規模時排序性能較好。
  • 面試官:那你能手寫一個快排嗎?
  • 你:
quick_sort = lambda array: array if len(array) <= 1 else quick_sort([item for item in array[1:] if item <= array[0]]) + [array[0]] + quick_sort([item for item in array[1:] if item > array[0]])

  

7、總結

快排是面試與考試中最高頻的一種排序算法(沒有之一),請你們務必理解與掌握,歡迎你們在評論區留言,同時也但願你們轉發分享讓更多的人愛上python這門語言。性能

相關文章
相關標籤/搜索