目录
快速排序(递归优化版):(筛选更好的基准数,较短区间采用插入排序)
1、快速排序概述
快速排序是对冒泡排序算法的一种改进。冒泡排序每次只能交换相邻的两个元素,而快速排序是跳跃式的交换,交换的距离很大,因此总的比较和交换次数少了很多,速度也快了不少。 由 C.A.R.Hoare(Charles Antony Richard Hoare,东尼·霍尔)在 1962 年提出。
快速排序是一个不稳定的算法,在经过排序之后,可能会对相同值的元素的相对位置造成改变。快速排序基本上被认为是相同数量级的所有排序算法中,平均性能最好的。
原理:
(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。
(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于或等于分界值。
(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。
图示:
时间和空间复杂度:
平均时间复杂度:O(nlogn)
空间复杂度:O(nlogn)
2、快速排序分类
快速排序(递归版)、
快速排序(递归优化版):(筛选更好的基准数,较短区间采用插入排序)
3、代码实现及运行结果
main函数:
public static void main(String[] args) {
long starttime1=System.nanoTime();
System.out.println("快速排序(递归版)");
int[] nums1=new int[]{77,33,45,55,90,30,67,3,1,2,3,4,5,6,68,98,99,76,65,66,33,43,32,43};
quicksort(nums1,0,nums1.length);
for (int m = 0; m < nums1.length ; m++){
System.out.print(nums1[m]+",");
}
System.out.println();
long endtime1=System.nanoTime();//200ns
System.out.println("程序运行时间:"+(endtime1-starttime1)+"ns");
long starttime2=System.nanoTime();
System.out.println("快速排序(递归优化版)");
int[] nums2=new int[]{77,33,45,55,90,30,67,3,1,2,3,4,5,6,68,98,99,76,65,66,33,43,32,43};
quicksort1(nums2,0,nums2.length);
for (int m = 0; m < nums2.length ; m++){
System.out.print(nums2[m]+",");
}
System.out.println();
long endtime2=System.nanoTime();//200ns
System.out.println("程序运行时间:"+(endtime2-starttime2)+"ns");
}
快速排序(递归版)
代码:
public static void quicksort(int[] num ,int start,int end) {
if ((end-start)<2)return;
//挖坑填数法
int temp=num[start];
int left=start;//左标
int right=end-1;//右标
int c=0;//标识方便左右交换填坑
while (left<right){
if (c==0) {
if(num[right]>=temp){right--;continue;}
num[left]=num[right];
left++;
c=1;
continue;
}
if (c==1) {
if (num[left]<temp){left++;continue;}
num[right]=num[left];
right--;
c=0;
continue;
}
}
num[left]=temp;
quicksort(num,0,left);
quicksort(num,left+1,end);
}
运行结果:
快速排序(递归版)
1,2,3,3,4,5,6,30,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
程序运行时间:1893400ns
快速排序(递归优化版)
代码:
//插入排序
public static void sort(int[] num1,int start,int end){
int[] num=new int[end-start];
for (int i = start; i <end ; i++) {
num[i]=num1[start+i];
}
if(num.length<2)return;
int index;//标志即将插入元素
int count=0;
for (int i = 1; i <num.length ; i++) {//开始逐个插入
index=num[i];//给index赋值操作
int j;
for ( j=i-1; j >=0; j--) {//在有序序列中倒序查找比较
count++;
if(num[j]<=index)break;//查找到index插入位置
num[j+1]=num[j];//后移空出新的位置
}
num[j+1]=index;//插入index
}
}
//快速排序优化
public static void quicksort1(int[] num,int start,int end){
if ((end-start)<2)return;
//过长时,选择适当基准数
if((end-start)>10){
int[] buf=new int[(end-start)/3+1];
int j=0;
for (int i = start; i <end ; i+=3) {
buf[j]=num[i];
j++;
}
sort(buf,0,buf.length);
int m=buf[buf.length/2];
for (int k = 0; k < end-start; k++) {
if(m==num[k]){
int b=num[start];
num[start]=m;
num[k]=b;
break;}
}
}
//挖坑填数法
int temp=num[start];
int left=start;//左标
int right=end-1;//右标
int c=0;//标识方便左右交换填坑
while (left<right){
if (c==0) {
if(num[right]>=temp){right--;continue;}
num[left]=num[right];
left++;
c=1;
continue;
}
if (c==1) {
if (num[left]<temp){left++;continue;}
num[right]=num[left];
right--;
c=0;
continue;
}
}
num[left]=temp;
//对左右区间分别递归排序,长度小于10 时使用插入排序优化
if(left<10){
sort(num,0,left);
}else quicksort(num,0,left);
if ((end-left-1)<10){
sort(num,left+1,end);
} else quicksort(num,left+1,end);
}
运行结果:
快速排序(递归优化版)
1,2,3,3,4,5,6,30,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
程序运行时间:1014400ns