一、快速排序(平均运行时间O(NlogN)、最坏O(N^2))
(一)最大的优点是其非常精练和高度优化的内部循环
由一个判断、一个自增自减运算、一个交换组成。(具体程序附在后面)
(二) 最常用的快速排序的实现——经典快速排序
输入存放在数组里,不产生额外的数组。
将数组S快排 qusicsort(S),其基本算法大概由4步构成
1,S的个数是0或1,则返回
2,按照#三数中值分割法#获得枢纽元。
3,分割成比枢纽元小的集合S1和比枢纽元大的集合S2
4,返回qusicsort(S1),qusicsort(S2)
(三)未优化前 程序
/*
* 1,快排的驱动程序
* */
public static void quicksort(int [] a) {
quicksort(a,0,a.length-1);
}
/*
/*
* 2,分割数组的程序
* */
private static int partition(int[]a,int left,int right){
nt pivot=a[left]; //选用第一个数为枢纽值
while(left<right){
while(left<right&&pivot<=a[right])
right--;
swap(a, left, right);
while(left<right&&pivot>=a[left])
left++;
swap(a, left, right);
}
return left;
}
/*
* 3,快排的主例程
* */
private static void quicksort(int [] a,int left,int right ) {
int pivotPos;
if(left<right) {
pivotPos=partition(a, left, right);
quicksort(a, left, pivotPos-1);
quicksort(a, pivotPos+1,right);
}
}
/*
* 交换方法
* */
private static void swap(int []a,int i,int j) {
if(a[i]==a[j])
return ;
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
()未优化前 程序
(四)优化
1优化选取枢纽元
方法:三数中值分割法
枢纽元最好的选择是数组的中位数即第N/2最大的数。
如果直接算出中位数,会明显减慢快排的速度
因此需要预估中位数,预估值通过最左端,最右端和中心位置的三个元素的中值得到,从而作为枢纽元
2优化不必要交换
将privot备份到a[0]中,然后在之前swap交换的地方改为替换,最终当leftyuright会合即找到了枢纽的位置时.再将a[0]赋值回a[left].少了多次交换数据的操作.
3小数组
当数组个数N<=20.快排不如插入排序。
当快排递归到截至范围CUTOFF(right-low)<10采用插入排序,节省大约15%的运行时间.
4优化递归操作
5优化的程序
/*
* 1,快排的驱动程序
* */
public static void quicksort(int [] a) {
quicksort(a,0,a.length-1);
/*
/*
* 2,三数中值选枢纽的程序
* */
private static int median3(int[]a,int left,int right) {
int median=(left+right)/2;
if(a[left]>a[right])
swap(a,left,right); //保证左端小
if(a[median]>a[right])
swap(a,median,right); //保证中间小
if(a[median]>a[left])
swap(a,left,median); //保证左端中值
return a[left];
}
/*
* 3,分割数组的程序2
* */
private static int partition2(int[]a,int left,int right) {
int pivot=median3(a,left,right); //优化选取枢纽
while(left<right){
while(left<right&&pivot<=a[right])
right--;
a[left]=a[right]; //替换变为交换
while(left<right&&pivot>=a[left])
left++;
a[right]=a[left]; //替换变为交换
}
a[left]= pivot;
return left;
}
/*
* 4,快排的主例程
* */
private static void quicksort(int [] a,int left,int right ) {
int pivotPos;
if(left<right) {
pivotPos=partition2(a, left, right); // 第二个分割函数
quicksort(a, left, pivotPos-1);
quicksort(a, pivotPos+1,right);
}
}