本打算學一波快速排序,查了查資料,嚇一大跳,說阮一峰大神的快排是不對的,以此開始了一大波大神針對這個問題的各種觀點。感興趣的可以看看知乎這篇帖子:
不管對還是錯,阮一峰大神的快排思路是對的:
在資料集之中,選擇一個元素作為"基準"(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));
};
複製程式碼
如果有大神知道,希望能告知優化方法。