今天旧活新整,发现了一个快速排序的更易理解版,还是在原有空间进行排序,不过能更好体现快速排序的策略特点。
好活共赏。
//快速排序不是稳定排序。最坏时间复杂度为O(n2) 最好情况 O(nlogn) 平均情况 O(nlogn)
function quicksort(start, end, nums) {
if (start > end) {
return;
}
let pivot = nums[end],
i = start - 1; //i最开始没有确定比枢纽值小的子序列
for (let j = start; j < end; j++) {
if (nums[j] <= pivot) {
i++;
[nums[i], nums[j]] = [nums[j], nums[i]];
}
}
//i是比枢纽值小的子序列的最后一个
//i+1确定了枢纽值的位置
[nums[i + 1], nums[end]] = [pivot, nums[i + 1]];
quicksort(start, i, nums);
quicksort(i + 2, end, nums)
}
function randomNums(len) {
let arr = [];
for (let i = 0; i < len; i++) {
arr[i] = Number.parseInt(Math.random() * 1000);
}
return arr;
}
function main() {
let nums = randomNums(10);
let numStandard = [...nums];
quicksort(0, nums.length - 1, nums);
numStandard.sort((a, b) => a - b);
console.log(nums);
console.log(numStandard);
console.log(numStandard.toString() == nums.toString());
}
main();
快速排序基于分治法,通过选取枢轴值,将原数组分解为两半,一半均比枢轴值小,一半均比枢轴值大,不断拆分子问题。 今天这个版本,更易体现这种枢轴划分的特点。
let pivot = nums[end],
i = start - 1; //i最开始没有确定比枢纽值小的子序列
for (let j = start; j < end; j++) {
if (nums[j] <= pivot) {
i++;
[nums[i], nums[j]] = [nums[j], nums[i]];
}
}
注意看, 结果上[start,i]这个双闭区间中的元素全比枢轴值小,妙啊,比双指针的while循环更易理解,属实拿捏了。
下面是最常见快排的实现
//快速排序不是稳定排序。最坏时间复杂度为O(n2) 最好情况 O(nlogn) 平均情况 O(nlogn)
function quicksort(start, end, nums) {
if (start > end) {
return;
}
let pivot = nums[start],
l = start,
r = end;
while (l != r) {
while (nums[r] >= pivot && l < r) {
r--;
}
while (nums[l] <= pivot && l < r) {
l++;
}
if (l < r) {
[nums[l], nums[r]] = [nums[r], nums[l]];
}
}
[nums[start], nums[l]] = [nums[l], pivot];
quicksort(start, l - 1, nums);
quicksort(l + 1, end, nums)
}
function randomNums(len) {
let arr = [];
for (let i = 0; i < len; i++) {
arr[i] = Number.parseInt(Math.random() * 1000);
}
return arr;
}
function main() {
let nums = randomNums(10);
let numStandard = [...nums];
quicksort(0, nums.length - 1, nums);
numStandard.sort((a, b) => a - b);
console.log(nums);
console.log(numStandard);
console.log(numStandard.toString() == nums.toString());
}
main();
再整个快排随机版,也就那么回事。
//快速排序不是稳定排序。最坏时间复杂度为O(n2) 最好情况 O(nlogn) 平均情况 O(nlogn)
function quicksort(start, end, nums) {
if (start > end) {
return;
}
let pivotIndex = Number.parseInt(Math.random() * (end - start) + start);
let pivot = nums[pivotIndex],
l = start,
r = end;
//随机化就体现在随机选取枢轴,然后与第一个交换
[nums[start], nums[pivotIndex]] = [nums[pivotIndex], nums[start]];
while (l != r) {
while (nums[r] >= pivot && l < r) {
r--;
}
while (nums[l] <= pivot && l < r) {
l++;
}
if (l < r) {
[nums[l], nums[r]] = [nums[r], nums[l]];
}
}
//l==r
[nums[start], nums[l]] = [nums[l], pivot];
quicksort(start, l - 1, nums);
quicksort(l + 1, end, nums)
}
function randomNums(len) {
let arr = [];
for (let i = 0; i < len; i++) {
arr[i] = Number.parseInt(Math.random() * 1000);
}
return arr;
}
function main() {
let nums = randomNums(10);
let numStandard = [...nums];
quicksort(0, nums.length - 1, nums);
numStandard.sort((a, b) => a - b);
console.log(nums);
console.log(numStandard);
console.log(numStandard.toString() == nums.toString());
}
main();
快排刻烟吸肺。