比如说对数组快排的思路就是:
- 选取一个基准(可以选数组的开头最为基准,令 i = 0 ;j = array.length -1)
- 从arr[j]向前遍历(j--),当该值大于基准,则交换,退出循环(break)。
- 从arr[i]向后遍历(i++),当该值大于基准,则交换,退出循环(break)。
- 重复步骤2和步骤3,直到 i == j。此时a[i] 左边都小于a[i],右边都大于a[i]。
- 根据下标分别递归左右两边的部分,注意一下递归出口就ok了。
/**
* @author vigdxx@gmail.com
* @param {Array} arr 待排序数组
*/
function quickSort(arr) {
/**
* @description 对数组的一部分进行排序,快排的基准为取待排序部分首项
* @param {Number} i 待排序部分开始位置
* @param {Number} j 待排序部分结束位置
*/
function sort(i,j) {
if(i >= j) {return} // 递归出口
let start = i;
let end = j;
while(i < j) {
for(;j>i;j--) {
if(arr[i] > arr[j]) {
[arr[j],arr[i]] = [arr[i],arr[j]];
break;
}
}
// 这个地方用 ++i,可以少一次比较
for(;i<j;++i) {
if(arr[i] > arr[j]) {
[arr[j],arr[i]] = [arr[i],arr[j]];
break;
}
}
}
// 此时 i == j , arr[i] 左边的小于等于 arr[i],右边的大于arr[i]
sort(start,i-1);
sort(i+1,end)
}
sort(0,arr.length - 1);
return arr;
}
复制代码
快排的时间复杂度是 O(nlogn),是一种不稳定的排序算法。当出现 大量重复数据时
,上述快排算法并不是一种最有解,他的改进型:三向切分快速排序是一种更高效的算法。其思想就是把一个数组分为三部分,一部分小于pivot,一部分等于pivot,还有一部分大于pivot。代码如下
function quickSort3way(arr) {
function sort3way(low, high) {
if(low >= high) {return}
let lt = low;//小于pivot的元素交换点
let gt = high;//大于pivot的元素交换点
let i = low +1;
let pivot = arr[low];
while(i <= gt) {
if (arr[i] < pivot) {
[arr[i], arr[lt]] = [arr[lt], arr[i]];
i++;
lt++;
} else if (arr[i] === pivot) {
i++;
} else if (arr[i] > pivot) {
[arr[i], arr[gt]] = [arr[gt], arr[i]];
gt--;
//此时 不能i++,因为交换后不能保证 arr[i] 等于还是小于 pivot
}
}
sort3way(low,lt-1);
sort3way(gt+1,high);
}
sort3way(0,arr.length-1);
return arr;
}
复制代码