对于快速排序的原理就是每次选一个值,然后左边是小于这个值右边是大于这个值,但写程序做了大量的修改,最终性能与希尔插入排序和双轴快排做比较,都是不稳定排序,但从随机数来看总体慢于双轴快排,略等于希尔插入排序,现在逻辑还不够简练,有时间优化下的话性能应该还能有一定的提升。下面是代码和测试数据。
import java.time.LocalDateTime;
import java.util.Arrays;
/*
*数组方法
*/
public class ArrTool {
//自建随机数生成器
private static int seed = LocalDateTime.now().getSecond();
//n到b范围的随机数
public static int myrandom(int n, int b){
seed = 37 * seed + 137;
if (seed < 0) {
seed *= -1;
}
return seed%(b+1-n)+n;
}
//调用接口
private static void quickSort(int[] arr){
ArrTool.quickSort2(arr,0,arr.length-1);
}
//快速排序优化
private static void quickSort2(int[] arr,int left,int right){
//随机选取比较参数
Integer compareIndex = ArrTool.myrandom(left,right);
Integer x = arr[compareIndex];
Integer point = compareIndex;//替换点实际位置
Integer index = 0; //下一替换点
Integer count = 0; //交换次数
Boolean isContinue = Boolean.FALSE;
for (int i = left; i < right+1; i++) {
if (i<right && arr[i] > arr[i+1]){
isContinue = Boolean.TRUE;
}
if (arr[i] > x ) {
if (count==0){
index = i;
}
count++;
}else{
if (count==0){
continue;
}
int temp = arr[index] ;
arr[index]= arr[i];
arr[i] = temp;
if (arr[index]==x){
point =index;
}
index ++;
if (temp==x && index>0){
index--;
}
}
}
if (x!=arr[right]){
arr[point]= arr[right-count];
arr[right-count] = x;
}
if (right-left-count>1 && isContinue){
quickSort2(arr,left,right-count-1);
}
if (count>1 && isContinue){
quickSort2(arr,right-count+1,right);
}
}
public static void shellSort(int[] a) {
long start = System.currentTimeMillis();
int n =a.length;
int j,gap;
for (gap = n/2; gap > 0; gap /=2) {
for (j = gap; j < n; j++) {
if (a[j]<a[j-gap]) {
int temp = a[j];
int k = j -gap;
while (k>=0&&a[k]>temp) {
a[k+gap] = a[k];
k-=gap;
}
a[k+gap]=temp;
}
}
}
long end = System.currentTimeMillis();
System.out.println("希尔插入排序完成的时间:"+(end - start)+"毫秒");
}
public static void main(String[] args) {
int[] arr =new int[]{9,5,9,6,7,9,10,1,5,8,4,3,2,1,5,9,8,6,4,7,5,2};
quickSort(arr);
System.out.println(Arrays.toString(arr));
/** 性能测试
int [] arr1=new int[100000];
int [] arr2=new int[100000];
int [] arr3=new int[100000];
for (int i = 0; i < 100000; i++) {
int x = ArrTool.myrandom(0,1000);
arr1[i] =x;
arr2[i] =x;
arr3[i] =x;
}
ArrTool.shellSort(arr1);
long start = System.currentTimeMillis();
Arrays.sort(arr2);
long end = System.currentTimeMillis();
System.out.println("系统快速排序完成的时间:"+(end - start)+"毫秒");
long start1 = System.currentTimeMillis();
quickSort(arr3);
long end1 = System.currentTimeMillis();
System.out.println("手写板快速排序完成的时间:"+(end1 - start1)+"毫秒");
*/
/**
数据正确暴力验证
int n=0;
while (n<100000){
int [] arr2=new int[1000];
for (int i = 0; i < 1000; i++) {
arr2[i] =ArrTool.myrandom(0,1000) ;
}
quickSort(arr2);
for (int i = 0; i < 999; i++) {
if (arr2[i]>arr2[i+1]){
System.out.println(存在错误数据,验证失败);
}eles{
System.out.println(全部正确,验证成功);
}
n++;
}
*/
}
}
数据量10万
希尔插入排序完成的时间: 18毫秒 21毫秒 65毫秒
系统快速排序完成的时间: 19毫秒 34毫秒 68毫秒
手写板快速排序完成的时间: 56毫秒 66毫秒 50毫秒.
数据量100万
希尔插入排序完成的时间: 174毫秒 180毫秒 174毫秒
系统快速排序完成的时间: 93毫秒 122毫秒 174毫秒
手写板快速排序完成的时间:208毫秒 240毫秒 275毫秒
数据量1000万
希尔插入排序完成的时间: 1590毫秒 1574毫秒 1550毫秒
系统快速排序完成的时间: 431毫秒 456毫秒 440毫秒
手写板快速排序完成的时间:1662毫秒 1629毫秒 1639毫秒
数据量1亿
希尔插入排序完成的时间:16159毫秒 15961毫秒 17149毫秒
系统快速排序完成的时间:4096毫秒 4177毫秒 4201毫秒
手写板快速排序完成的时间:16168毫秒 15063毫秒 15851毫秒
总结:只是初步优化过的快排性能就已经很好了,而且是全递归运算,基本达到了理论运算水平,优化后基本不会内存泄露,基本理论上快排并没有多大优势,但合并优化其他排序方式能得到最大性能提升。比如java中的双轴快排。