本来写了一个排序合集,不过快排的优化方案比较多,单独拿了出来,下面用到的插入排序 代码在合集中
public void quickSort(int[] a, int l, int r) {
if (l < r) {
int s = partition(a, l, r);
quickSort(a, l, s - 1);
quickSort(a, s + 1, r);
}
}
private int partition(int a[], int l, int r) { //找到标志位
int p = a[l];
int j = l;
int m;
for (int i = l + 1; i <= r; i++) {
if (a[i] < p) {
m = a[j + 1];
a[j + 1] = a[i];
a[i] = m;
j++;
}
}
m = a[l];
a[l] = a[j];
a[j] = m;
return j;
}
快速排序的优化:
public void quickSort(int[] a, int l, int r) {
if (r <= l) {
return;
}
// if(r-l<=15){ //优化1 小于15个元素时采用插排
// insertSort(a);
// return ;
// }
int s = partition(a, l, r);
quickSort(a, l, s - 1);
quickSort(a, s + 1, r);
}
private int partition(int a[], int l, int r) { //找到标志位
int m;
/*优化2 选择l~r之间随机数为标志,这种方法在数组接近有序数组时能大幅提高效率*/
m = a[l];
int rand = (int) (Math.random() * (r - l + 1));
a[l] = a[rand + l];
a[rand + l] = m;
int p = a[l];
int j = l;
for (int i = l + 1; i <= r; i++) {
if (a[i] < p) {
m = a[j + 1];
a[j + 1] = a[i];
a[i] = m;
j++;
}
}
m = a[l];
a[l] = a[j];
a[j] = m;
return j;
}
private int partition2(int a[], int l, int r) {
/*优化3 从后向前搜索*/
int m;
m = a[l];
int rand = (int) (Math.random() * (r - l + 1));
a[l] = a[rand + l];
a[rand + l] = m;
int p = a[l];
int i = l + 1, j = r;
while (true) {
while (i <= r && a[i] < p) {
i++;
}
while (j >= l + 1 && a[j] > p) {
j--;
}
if (i > j) {
break;
}
m = a[i];
a[i] = a[j];
a[j] = m;
i++;
j--;
}
m = a[j];
a[j] = a[l];
a[l] = m;
return j;
}
private void quickSort3(int a[], int l, int r) {
if (r <= l) {
return;
}
/*优化4 3路排序 分为< = > 三部分 可快速处理重复元素的排序*/
int m;
m = a[l];
int rand = (int) (Math.random() * (r - l + 1));
a[l] = a[rand + l];
a[rand + l] = m;
int p = a[l];
int lt = l;//a[l+1...lt]<p
int gt = r + 1;//a[gt...r]>p
int i = l + 1;//[alt...i]=p
while (i < gt) {
if (a[i] < p) {
m = a[i];
a[i] = a[lt + 1];
a[lt + 1] = m;
lt++;
i++;
} else if (a[i] > p) {
m = a[i];
a[i] = a[gt - 1];
a[gt - 1] = m;
gt--;
} else {
i++;
}
}
quickSort3(a, l, lt - 1);
quickSort3(a, gt, r);
}
测试中随机生成了1000000个10以内的随机数,排序完成时间如下(mm):
随机生成1000000个1000000内的数据,排序完成时间如下(mm):
第一个时间是优化方案3,第二个是优化4,可见三路快排更适合处理数组中拥有大量重复数据的情况,而在数据重复较少的情况下,三路快排就不如另一种方案了,可以在实际中选择使用的方案