快排1.0版本
选数组最后一个元素为哨兵,将前面的元素(除了最后一个元素的数组)进行左右区间划分,使得前面元素比哨兵小的在左边,比哨兵大的在右边。划分区间算法
快排每一轮保证了哨兵元素的位置正确
最坏时间复杂度为O(n^2)
function quickSort(arr, left = 0, right = arr.length - 1) {
if (left < right) {
const pivotIndex = partition(arr, left, right);
quickSort(arr, left, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, right);
}
return arr;
}
function partition(arr, left, right) {
const pivot = arr[right];
let i = left;
// 分小于等于和大于区间
for (let j = left; j < right; j++) {
if (arr[j] <= pivot) {
// Swap elements at indices i and j
[arr[i], arr[j]] = [arr[j], arr[i]];
i++;
}
}
// 区分结束后,将小于区间的右边一个位置和最后一个哨兵元素位置互换
// Swap pivot element with the element at index i
[arr[i], arr[right]] = [arr[right], arr[i]];
return i;
}
const arr = [4, 2, 6, 3, 7, 9, 0];
const sortedArray = quickSort(arr);
console.log(sortedArray); // 输出:[0, 2, 3, 4, 6, 7, 9]
快排1.0版本另一种实现
时间复杂度
(() => {
function Quick(list) {
if (list.length == 0) {
return [];
}
let pivot = list[0];
let lesser = [];
let greater = [];
for (let i = 1; i < list.length; i++){ //快排:安装基准值排序,小于基准值放在左边,大于放在右边
if (list[i] < pivot) {
lesser.push(list[i]);
} else {
greater.push(list[i]);
}
}
return Quick(lesser).concat(pivot,Quick(greater));
}
let res=Quick([44,75,23,43,55,12,64,77])
console.log(res);
})()
快排2.0版本
let arr = [3, 5, 6, 7, 8, 3, 4, 5];
//划分小于、等于、大于区间
function cutting(arr, num, pleft, pright) {
let left = pleft - 1;
let right = pright + 1;
for (let i = pleft; i < pright + 1; i++) {
if (i == right) {
break;
}
if (arr[i] < num) {
[arr[left + 1], arr[i]] = [arr[i], arr[left + 1]];
left++;
} else if (arr[i] == num) {
continue;
} else {
[arr[i], arr[right - 1]] = [arr[right - 1], arr[i]];
right--;
//使得下轮比较从右边交换过来的数
i--;
}
}
//返回小于、大于区间的右、左边界
return [left, right];
}
function sort(arr, left, right) {
if (left >= right) {
return;
}
let mid = cutting(arr, arr[right], left, right);
sort(arr, left, mid[0]);
sort(arr, mid[1], right);
}
sort(arr, 0, arr.length - 1);
console.log(arr);
快排3.0版本
let arr = [3, 5, 6, 7, 8, 3, 4, 5];
//划分小于、等于、大于区间
function cutting(arr, num, pleft, pright) {
let left = pleft - 1;
let right = pright + 1;
for (let i = pleft; i < pright + 1; i++) {
if (i == right) {
break;
}
if (arr[i] < num) {
[arr[left + 1], arr[i]] = [arr[i], arr[left + 1]];
left++;
} else if (arr[i] == num) {
continue;
} else {
[arr[i], arr[right - 1]] = [arr[right - 1], arr[i]];
right--;
//使得下轮比较从右边交换过来的数
i--;
}
}
//返回小于、大于区间的右、左边界
return [left, right];
}
function sort(arr, left, right) {
if (left >= right) {
return;
}
//取区间随机值和最后一个数交换
let rand = left + parseInt(Math.random() * (right - left + 1));
[arr[right], arr[rand]] = [arr[rand], arr[right]];
let mid = cutting(arr, arr[right], left, right);
sort(arr, left, mid[0]);
sort(arr, mid[1], right);
}
sort(arr, 0, arr.length - 1);
console.log(arr);