排序——快速排序

66 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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);
}