HTML5學堂-碼匠:前幾期「算法之旅」跟你們分享了冒泡排序法和選擇排序法,它們都屬於時間複雜度爲O(n^2)的「慢」排序。今天跟你們分享多種排序算法裏使用較普遍,速度快的排序算法 —— 快速排序法 [ 平均時間複雜度爲O (n logn) ]。html
Tips 1:關於「算法」及「排序」的基礎知識,在此前「選擇排序法」中已詳細講解,可點擊文後的相關文章連接查看,在此再也不贅述。算法
Tips 2:若是無特殊說明,本文的快速排序是從小到大的排序。數組
快速排序是一種劃分交換排序,它採用分治的策略,一般稱其爲分治法。函數
基本思想:將原問題分解爲若干個規模更小但結構與原問題類似的子問題。遞歸地解決這些子問題,而後將這些子問題的結果組合成原問題的結果。ui
從序列中任選一個數做爲「基準」;code
全部小於「基準」的數,都挪到「基準」的左邊;全部大於等於「基準」的數,都挪到「基準」的右邊;htm
在此次移動結束以後,該「基準」就處於兩個序列的中間位置,再也不參與後續的排序;blog
針對「基準」左邊和右邊的兩個子序列,不斷重複上述步驟,直到全部子序列只剩下一個數爲止。排序
現有一個序列爲 [8, 4, 7, 2, 0, 3, 1],以下演示快速排序法如何對其進行排序。遞歸
先獲取基準的索引值,再使用splice數組方法取出基準值。
Tips:該實例中, 基準的索引值 = parseInt(序列長度 / 2)
Tips:splice方法會改變原始數組。例如,arr = [1, 2, 3]; 基準索引值爲1,基準值爲2,原始數組變爲arr = [1, 3];
與「基準」比較大小,並拆分爲兩個子序列
小於「基準」的數存儲於leftArr數組當中,大於等於「基準」的數存儲於rightArr數組當中
Tips:固然,也能夠將 小於等於「基準」的數存於leftArr,大於「基準」的數存於rightArr
因爲要遍歷序列,將每個數與「基準」進行大小比較,因此,須要藉助for語句來實現
定義一個函數,形參用於接收數組
實現遞歸調用遍歷子序列,用concat數組方法組合子序列的結果
遞歸調用的過程當中,子序列的長度等於1時,則中止遞歸調用,返回當前數組。
最壞狀況:每一次選取的「基準」都是序列中最小的數/最大的數,這種狀況與冒泡排序法相似(每一次只能肯定一個數[基準數]的順序),時間複雜度爲O(n^2)
最好狀況:每一次選取的「基準」都是序列中最中間的一個數(是中位數,而不是位置上的中間),那麼每次都把當前序列劃分紅了長度相等的兩個子序列。這時候,第一次就有n/二、n/2兩個子序列,第二次就有n/四、n/四、n/四、n/4四個子序列,依此類推,n個數一共須要logn次才能排序完成(2^x=n,x=logn),而後每次都是n的複雜度,時間複雜度爲O(n logn)
最壞狀況:須要進行n‐1 次遞歸調用,其空間複雜度爲 O(n)
最好狀況:須要logn次遞歸調用,其空間複雜度爲O(logn)
快速排序是一種不穩定排序算法
例如:現有序列爲[1, 0, 1, 3],「基準」數字選擇爲第二個1
在第一輪比較以後,變成了[0, 1, 1, 3],左序列爲[0],右序列爲[1, 3](右序列的1是此前的第一個1)
不難發現,原序列的兩個1的前後順序被破壞了,改變了前後順序,天然就是「不穩定」的排序算法了
在此前的「冒泡排序法」一文當中,咱們詳細講解過O是什麼,在此就很少說了,直接上圖吧