开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第32天,[点击查看活动详情]
快速排序
通过一趟排序将待排记录分隔两部分,一个比关键字小,一个比关键字大。分别对这两部分记录继续进行排序,整合。\
特点
时间复杂度:O(nlog2n)\
空间复杂度:S(1);
是不稳定的.
单路快速排序
public class QuickSort{
public static void main(String[] args){
int[] arr = new int[20];
Random random=new Random();
for(int i =0;i<arr.length;i++){
arr[i]=random.nextInt(50);
}
quickSort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
private static void quickSort(int[] arr,int l ,int r){
//优化,10个为一小组
if(r-l<=10){
ShellSort.shellSort(arr,l,r);
return;
}
int p=partition(arr,l,r);
quickSort(arr,l,p-1);
quickSort(arr,p+1,r);
}
private static int partition(int[] arr,int l ,int r){
//2,优化-避免是顺序的数组排序
swap(arr,l,(int)(Math.random()*(r-l+1)+l));//
int v =arr[l];
int j=l;
for(int i=l+1;i<=r;i++){
if(arr[i]<v){
swap(arr,j+1,i);
j++
}
}
swap(arr,l,j);
return j;
}
private static void swap(int[] arr,int i,int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
出现极端情况,类似于链表。
双路快速排序
可以解决等于的问题。把等于散布到左右两边,左右两边包含等于去排
方差小的双路快排会快,因为有好多相等的值。
双路的速度比单路会快些。
private static void quickSort(int[] arr,int l,int r){
if(l>=r){
return;
}
int p = partion(arr,l,r);
quickSort(arr,l,p-1);
quickSort(arr,p+1,r);
}
private static int partion(int[] arr,int l,int r){
swap(arr,l,(int)(Math.random()*(r-l+1)+l));
int v=arr[l];//中间值
int i=l+1;
int j=r;
while(true){
while(i<=r && arr[i]<v){
i++;
}
while(j>=l+1 && arr[j]>v){
j--;
}
if(i>j){
break;
}
swap(arr,i,j);
i++;
j--;
}
swap(arr,l,j);
return j;
}
三路快速排序
单路快排没有考虑等于的情况。
双路快排虽然考虑等于情况,但它只是把等于分到两个部分去算。
三路快排是把等于的情况单独列出来,分为3个部分。
也是为了解决大量重复元素。
速度快
private static void quickSort(int[] arr,int l,int r){
if(l>=r){
return;
}
//partion
swap(arr,l,(int)(Math.random()*(r-l+1)+l));
int v=arr[l];
int lt=l;
int gt=r+1;
int i=l+1;
while(i<gt){
if(arr[i]<v){
swap(arr,lt+1,i);
lt++;
i++;
}else if(arr[i]>v){
swap(arr,i,gt-1);
gt--;
}else{
i++;
}
}
swap(arr,l,lt);
quickSort(arr,l,lt);
quickSort(arr,gt,r);
}