快速排序(英語:Quicksort),又稱劃分交換排序(partition-exchange sort),簡稱快排,一種排序算法,最先由東尼·霍爾提出。在平均情況下,排序n個項目要O(nLogn)次比較。在最壞情況下則須要O(n^2)次比較,但這種情況並不常見。事實上,快速排序O(nLogn)一般明顯比其餘算法更快,由於它的內部循環(inner loop)能夠在大部分的架構上頗有效率地達成
快速排序可能你們都學過,在面試中也常常會遇到,哪怕你是作前端的也須要會寫,這裏會列舉兩種不一樣的快排代碼進行分析前端
爲了更深刻的理解,能夠看下面這張圖面試
咱們根據上面這張圖,來用文字描述一下算法
以上就是快速排序基本的一個實現思想。segmentfault
這是我最近看到的一種快排代碼數組
var quickSort = function(arr) { if (arr.length <= 1) { return arr; } var pivotIndex = Math.floor(arr.length / 2); var pivot = arr.splice(pivotIndex, 1)[0]; var left = []; var right = []; for (var i = 0; i < arr.length; i++) { if (arr[i] < pivot) { left.push(arr[i]); } else { right.push(arr[i]); } } return quickSort(left).concat([pivot], quickSort(right)); };
以上代碼的實現方式是,選擇一箇中間的數字爲基準點,用兩個數組分別去保存比基準數小的值,和比基準數大的值,最後遞歸左邊的數組和右邊的數組,用concat去作一個數組的合併。數據結構
對於這段代碼的分析:
缺點:架構
優勢:ide
那麼咱們接下來用另一種方式去實現快速排序函數
從上面這張圖,咱們用一個指針i去作了一個分割oop
下面咱們來看一下代碼的實現,整個代碼分紅三部分,數組交換,拆分,qsort(主函數)三個部分
先寫最簡單的數組交換吧,這個你們應該都懂
function swap(A, i ,j){ const t = A[i]; A[i] = A[j]; A[j] = t; }
下面是拆分的過程,其實就是對指針進行移動,找到最後指針所指向的位置
/** * * @param {*} A 數組 * @param {*} p 起始下標 * @param {*} r 結束下標 + 1 */ function dvide(A, p, r){ // 基準點 const pivot = A[r-1]; // i初始化是-1,也就是起始下標的前一個 let i = p - 1; // 循環 for(let j = p; j < r-1; j++){ // 若是比基準點小就i++,而後交換元素位置 if(A[j] <= pivot){ i++; swap(A, i, j); } } // 最後將基準點插入到i+1的位置 swap(A, i+1, r-1); // 返回最終指針i的位置 return i+1; }
主程序主要是經過遞歸去重複的調用進行拆分,一直拆分到只有一個數字。
/** * * @param {*} A 數組 * @param {*} p 起始下標 * @param {*} r 結束下標 + 1 */ function qsort(A, p, r){ r = r || A.length; if(p < r - 1){ const q = divide(A, p, r); qsort(A, p, q); qsort(A, q + 1, r); } return A; }
function swap(A, i, j) { const t = A[i]; A[i] = A[j]; A[j] = t; } /** * * @param {*} A 數組 * @param {*} p 起始下標 * @param {*} r 結束下標 + 1 */ function divide(A, p, r) { const x = A[r - 1]; let i = p - 1; for (let j = p; j < r - 1; j++) { if (A[j] <= x) { i++; swap(A, i, j); } } swap(A, i + 1, r - 1); return i + 1; } /** * * @param {*} A 數組 * @param {*} p 起始下標 * @param {*} r 結束下標 + 1 */ function qsort(A, p = 0, r) { r = r || A.length; if (p < r - 1) { const q = divide(A, p, r); qsort(A, p, q); qsort(A, q + 1, r); } return A; }
第二段的排序算法咱們減小了兩個O(n)的操做,獲得了必定的性能上的提高,而第一種方法數據規模足夠大的狀況下會相對來講比較慢一些,快速排序在面試中也經常出現,爲了筆試更好寫一些可能會有更多的前端會選擇第一種方式,但也會有一些爲難人的面試官提出一些算法中的問題。而在實際的項目中,我以爲第一種方式能夠少用。
本人最近寫的關於數據結構系列以下,歡迎你們看看點個贊哈:
js數據結構-棧
js數據結構-鏈表
js數據結構-隊列
js數據結構-二叉樹(二叉堆)
js數據結構-二叉樹(二叉搜索樹)