排序-快速排序

快速排序

public class Quick {
    private Quick(){}
    private static boolean less(Comparable v,Comparable w){
        return v.compareTo(w)<0;
    }
    private static void exch(Comparable[] a,int vIndex,int wIndex){
        Comparable temp = a[vIndex];
        a[vIndex] = a[wIndex];
        a[wIndex] = temp;
    }
    // 分区
    private static int partition(Comparable[] a,int lo,int hi){
        int i = lo;
        int j = hi+1;
        Comparable v = a[lo];
        while (true){
            while (less(a[++i],v)) if(i==hi) break;// 从左往右找到第一个大的
            while (less(v,a[--j])) if(j==lo) break;;// 从右往左找到第一个小的
            if(i>=j) break;
            exch(a, i, j);// 将找到的两个值交换
        }
        exch(a,lo,j);// 放回中间那么,左边都是小于该值的,右边都是大于该值的
        return j;// 中间值
    }
    private static void sort(Comparable[] a,int lo,int hi){
        if(lo>=hi)return;
        int mid = partition(a,lo,hi);
        sort(a,lo,mid-1);// 排序左边
        sort(a,mid+1,hi);// 排序右边
    }
    public static void sort(Comparable[] a){
        StdRandom.shuffle(a);// 打乱数组
        sort(a,0,a.length-1);
    }
}
实现策略

对数组进行切分,从左到右找到第一个大于切分值的元素,从右往左找到第一个小于切分值的元素,进行交换,lo与hi指针相遇时退出循环交换切分值和相遇指针元素,如此切分值左边都是小于切分值的元素,切分值右边都是大于切分值的元素。

分析

快速排序与归并排序互补,都是分治思想的体现,归并排序先进行排序后进行归并,快速排序先进行切分后进行排序。快速排序的最好情况是每次切分过后切分值都刚好落在中间,最坏情况是每次切分后有一边数组总是为空(切分每次刚好是最值),那么交换次数为1+2+…N-1+N~N²/2。尽管快速排序最差情况下为平方级别,比归并排序差,但是大量的工作证明快速排序运行时间在最差情况下的几率较小,并且我们仍然可以进行一些优化工作,减少这种情况发生的概率。总的来说快速排序的运行时间为1.39NlgN的某个常数因子下(同归并排序,但是移动次数是小于归并排序的)。
增长数量级
最差:N2(概率较小)
最好:N(三向切分)
平均:NlgN

改进
  1. 小数组使用插入排序
  2. 对于大量重复的数组可以使用三向切分的快速排序
三向切分的快速排序

三向切分的快速排序维护三个指针,小值上限lt,索引i,大值下限gt,

 // 三向切分,维护三个指针 
    public static void sort3Way(Comparable[] a,int lo,int hi){
        int lt = lo,i=lo+1,gt=hi;
        Comparable v = a[lo];
        while (lt<=gt){
            int cmp = a[i].compareTo(v);
            if(cmp<0) exch(a,lt++,i++);// 比较值小于切分值
       else if(cmp>0) exch(a,i,gt--);// i不进行自加,交换过来的值还要进行比较
          else i++;// 相等的情况下索引增加
        }
        sort3Way(a,lo,lt-1);// 排序左边
        sort3Way(a,gt+1,hi);// 排序右边
    }

切分过后lo~lt-1 小于切分支 lt~gt 等于切分值 gt+1~hi 大于切分值

动态示意图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值