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));
};
複製程式碼
這是從網上覆制下來的快排。快排是利用到了遞迴,那麼遞迴就是需要考慮空間複雜度。
先看,遞迴是怎麼執行的
{
code()
{
code()
{
code()
{
code()
// 從最裡面向外執行,而值是從外面一步步分解後傳進來,那麼系統就得儲存好沒一步被操作的值
}
}
}
}
複製程式碼
假設資料是佔用100MB記憶體,那麼運算過程儲存的值也就會是100Mb,當然只會比這個多,就不細算,只要知道這個概念就好。
我們改進一下,直接在原陣列上直接換值,而不用臨時引用型別儲存
var quickSort = function (arr) {
let len = arr.length
quickSortInternally(arr, 0, len-1)
// 遞迴
function quickSortInternally(arr, p, r) {
if(p>=r)return; // 陣列長度等於1的時候結束遞迴
let q = partition(arr, p, r)
quickSortInternally(arr, 0, q-1)
quickSortInternally(arr, q+1, r)
}
// 獲取區分點
function partition(arr, p, r) {
let i = p;
let pivot = arr[r] // 區分點
for(let j = i; j < r; j++){
if(arr[j]<pivot){
let tem = arr[j]
arr[j] = arr[i]
arr[i] = tem
++i
}
}
let tem = arr[r]
arr[r] = arr[i]
arr[i] = tem
return i;
}
}
複製程式碼
快排的最優狀態才是O(nlogn),最壞狀態是O(n2), 歸併排序最好最壞都是O(nlogn),那麼為什麼js中的排序不用歸併排序呢,就是因為歸併不是原地排序,需要額外的記憶體空間。如果快排按照第一個那樣寫,那還是用歸併排序把,因為第一個快排也不是原地排序。
快排的複雜度是看切分的深度,第二個寫的快排區分點是那最後一個做區分點,如果陣列是[1,2,3,4],這種順序完成了或者接近完成的[1,3,2,4,5],這種就會O(n2)的時間複雜度。那麼怎麼解決這種問題。 我們可以取三點然後在取一箇中間值(1,9,6;取6做區分點)。就會解決這種問題,直接嘗試修改一下吧。 當然第二個引數再加一個fun引數,比較陣列不都是[1,2,3]這樣的,很多時候是[{},{},{}]這樣的資料