Java 排序之快速排序及其优化

本来写了一个排序合集,不过快排的优化方案比较多,单独拿了出来,下面用到的插入排序 代码在合集中

Java之排序算法


 public void quickSort(int[] a, int l, int r) {
        if (l < r) {
            int s = partition(a, l, r);
            quickSort(a, l, s - 1);
            quickSort(a, s + 1, r);
        }

    }

    private int partition(int a[], int l, int r) {      //找到标志位
        int p = a[l];
        int j = l;
        int m;
        for (int i = l + 1; i <= r; i++) {
            if (a[i] < p) {
                m = a[j + 1];
                a[j + 1] = a[i];
                a[i] = m;
                j++;
            }
        }
        m = a[l];
        a[l] = a[j];
        a[j] = m;
        return j;
    }

快速排序的优化:

    public void quickSort(int[] a, int l, int r) {

        if (r <= l) {
            return;
        }
//        if(r-l<=15){    //优化1   小于15个元素时采用插排
//            insertSort(a);
//            return ;
//        }

        int s = partition(a, l, r);
        quickSort(a, l, s - 1);
        quickSort(a, s + 1, r);

    }

    private int partition(int a[], int l, int r) {      //找到标志位
        int m;
        /*优化2  选择l~r之间随机数为标志,这种方法在数组接近有序数组时能大幅提高效率*/
        m = a[l];
        int rand = (int) (Math.random() * (r - l + 1));
        a[l] = a[rand + l];
        a[rand + l] = m;

        int p = a[l];
        int j = l;

        for (int i = l + 1; i <= r; i++) {
            if (a[i] < p) {
                m = a[j + 1];
                a[j + 1] = a[i];
                a[i] = m;
                j++;
            }
        }
        m = a[l];
        a[l] = a[j];
        a[j] = m;
        return j;
    }


  private int partition2(int a[], int l, int r) {
        /*优化3  从后向前搜索*/
        int m;
        m = a[l];
        int rand = (int) (Math.random() * (r - l + 1));
        a[l] = a[rand + l];
        a[rand + l] = m;

        int p = a[l];
        int i = l + 1, j = r;
        while (true) {
            while (i <= r && a[i] < p) {
                i++;
            }
            while (j >= l + 1 && a[j] > p) {
                j--;
            }
            if (i > j) {
                break;
            }
            m = a[i];
            a[i] = a[j];
            a[j] = m;
            i++;
            j--;
        }
        m = a[j];
        a[j] = a[l];
        a[l] = m;

        return j;
    }

    private void quickSort3(int a[], int l, int r) {
        if (r <= l) {
            return;
        }
        /*优化4  3路排序 分为< = > 三部分 可快速处理重复元素的排序*/
        int m;
        m = a[l];
        int rand = (int) (Math.random() * (r - l + 1));
        a[l] = a[rand + l];
        a[rand + l] = m;

        int p = a[l];
        int lt = l;//a[l+1...lt]<p
        int gt = r + 1;//a[gt...r]>p
        int i = l + 1;//[alt...i]=p
        while (i < gt) {
            if (a[i] < p) {
                m = a[i];
                a[i] = a[lt + 1];
                a[lt + 1] = m;
                lt++;
                i++;
            } else if (a[i] > p) {
                m = a[i];
                a[i] = a[gt - 1];
                a[gt - 1] = m;
                gt--;
            } else {
                i++;
            }
        }
        quickSort3(a, l, lt - 1);
        quickSort3(a, gt, r);
    }

测试中随机生成了1000000个10以内的随机数,排序完成时间如下(mm):


随机生成1000000个1000000内的数据,排序完成时间如下(mm):


第一个时间是优化方案3,第二个是优化4,可见三路快排更适合处理数组中拥有大量重复数据的情况,而在数据重复较少的情况下,三路快排就不如另一种方案了,可以在实际中选择使用的方案


猜你喜欢

转载自blog.csdn.net/yforyoung/article/details/80463636
今日推荐