阮一峰快速排序

wade3po發表於2019-04-15

本打算學一波快速排序,查了查資料,嚇一大跳,說阮一峰大神的快排是不對的,以此開始了一大波大神針對這個問題的各種觀點。感興趣的可以看看知乎這篇帖子:

www.zhihu.com/question/27…

不管對還是錯,阮一峰大神的快排思路是對的:

在資料集之中,選擇一個元素作為"基準"(pivot)。

所有小於"基準"的元素,都移到"基準"的左邊;所有大於"基準"的元素,都移到"基準"的右邊。

對"基準"左邊和右邊的兩個子集,不斷重複第一步和第二步,直到所有子集只剩下一個元素為止。

先看看阮一峰大神的程式碼:

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));

};
複製程式碼

思路很清晰找出基準之後,左邊陣列右邊陣列和基準的陣列都很清晰。

那些說為什麼用splice(splice本身也有時間複雜度)、為什麼每次開闢新的left、right陣列等,這確實是這段程式碼的問題。但是阮一峰大神只是提供思路,這些問題都是能優化的。當時ES6也沒出來,以後還會有更多的陣列擴充套件,那不是能更簡單的實現快速排序,但是快速排序的思路是不變的。

我本來想把兩個都優化了,奈何能力有限,無法解決一直開闢新陣列的問題,也就是空間複雜度的問題:

var quickSort = function(arr) {    

 if (arr.length <= 1) { return arr; }    

  var pivot = arr[0];    

  var left = [];    

  var right = [];    

  var mid = [];    

  for (var i = 0; i < arr.length; i++){        

   if (arr[i] < pivot) {            

     left.push(arr[i]);        

   } else if (arr[i] > pivot){            

     right.push(arr[i]);        

    }else{            

      mid.push(arr[i]);        

   }    

}    

return quickSort(left).concat(mid, quickSort(right));

};
複製程式碼

如果有大神知道,希望能告知優化方法。

阮一峰快速排序

相關文章