Java排序之【快速排序】

依照书上写了3段代码,分别是以右端数据、首中尾取中值、先找出中间值作为枢纽,使用一百万随机数测试后发现,原始的快排最快,先找中间值的反而最慢。

代码如下

1:原始的

package LianXi;

import java.util.Arrays;
import java.util.Random;

//快速排序:先以数组末端作为标准,大于它的左端元素和小于它的右端元素作为一对进行交换
//最后将枢纽数据换到第二个数组首位
public class FastSort {
    static int i;

    static void sort(int[] a, int front, int end) {
        if (front >= end)
            return;
        i = div(a, front, end);
        sort(a, front, i - 1);
        sort(a, i + 1, end);
    }

    static int div(int[] a, int front, int end) {
        int temp = a[end];
        int l = front - 1;
        int r = end;
        while (true) {
            while (a[++l] < temp)
                ;
            while (r > 0 && a[--r] > temp)
                ;// 找到然后交换,while很精巧
            if (l >= r)
                break;
            else
                swap(a, l, r);
        }
        swap(a, l, end);
        return l;// 返回右边数组首位下标
    }

    static void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

    public static void main(String[] args) {
        long t1=System.currentTimeMillis();
        int size = 100;
        int[] a = new int[size];
        Random rand = new Random();
        for (int i = 0; i < 20; i++) {
            int n = rand.nextInt(size*5);
            a[i] = n;
        }
        sort(a, 0, a.length - 1);
        long t2=System.currentTimeMillis();
        System.out.println(t2-t1);
    }
}
2:先从首、中、尾找出中间值作为枢纽元素

package LianXi;

import java.util.Random;


public class FastSort2 {
    // 中值划分至少要4个数据,不然另外解决
    static void sort(int[] a, int front, int end) {
        int size = end - front + 1;
        if (size <= 3)//这里是可调节的地方,对于数据量50000来说,设置3或者10都好像没有区别
            manualsort(a, front, end);
        else {
            int temp = div(a, front, end);
            sort(a, front, temp - 1);
            sort(a, temp + 1, end);
        }
    }

    static int div(int[] a, int front, int end) {
        int temp = innersort(a, front, end);// temp接收中间值
        int left = front;
        int right = end - 1;
        while (true) {
            while (a[++left] < temp)
                ;
            while (a[--right] > temp)
                ;
            if (left >= right)
                break;
            else
                swap(a, left, right);
        }
        swap(a, end - 1, left);
        return left;
    }

    static int innersort(int[] a, int i, int j) {
        int mid = (i + j) / 2;
        if (a[i] > a[mid])
            swap(a, i, mid);
        if (a[i] > a[j])
            swap(a, i, j);
        if (a[mid] > a[j])
            swap(a, mid, j);
        swap(a, mid, j - 1);// 把中间值移到倒数第二个
        return a[j - 1];
    }

    static void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

    // 需要注意下标可能出现左边大于右边的情况
    static void manualsort(int[] a, int front, int end) {
        if (front >= end)
            return;
        else {
            for (int i = front + 1; i <= end; i++) {
                int j = i;
                int temp=a[i];
                while (--j >= front && a[j] > temp)
                    a[j + 1] = a[j];
                a[j + 1] = temp;
            }
        }
    }

    public static void main(String[] args) {
        long t1=System.currentTimeMillis();
        int size = 100;
        int[] a =new int[size];
        Random rand = new Random();
        //System.out.println("排序前:");
        for (int i = 0; i < a.length; i++) {
            int n = rand.nextInt(size*2);
            //System.out.print(n + " ");
            a[i] = n;
        }
        sort(a, 0, a.length - 1);
        //System.out.println("\n排序后:");
        //System.out.println(Arrays.toString(a));
        long t2=System.currentTimeMillis();
        System.out.println(t2-t1);
    }
}
3:先找出整个数组中间值,再排序

package LianXi;


import java.util.Random;

//先利用快排找出中间值
public class FindMid {
    static int[] a;
    static int mid;

    static void finalsort() {
        find(0, a.length - 1);// 中值已在中间
        swap(mid, a.length - 1);// 将中间值换到最后
        sort(0, a.length - 1);

    }

    static void sort(int f, int end) {
        if (end - f <= 0)
            return;
        int temp = div(f, end);
        sort(f, temp - 1);
        sort(temp + 1, end);
    }

    static void find(int f, int end) {
        if (end - f == 1) {
            if (a[f] > a[end])
                swap(f, end);
            return;// 如果只剩2个,排完即返回
        }
        int m = (f + end) / 2;
        int temp = div(f, end);
        if (temp == mid)// 如果枢纽下标为这个,说明枢纽即是中间值
            return;
        if (temp > m)
            find(f, temp - 1);// 这里不-1会无限循环
        else if (temp < m)
            find(temp + 1, end);
        else if (temp == m) {
            if (m > mid)
                find(f, temp - 1);
            else
                find(temp + 1, end);
        }

    }

    // 划分一次,返回枢纽下标
    static int div(int f, int end) {
        int l = f - 1;
        int r = end;
        int temp = a[end];
        while (true) {
            while (a[++l] < temp)
                ;
            while (r > l && a[--r] > temp)
                ;
            if (r <= l)
                break;
            else
                swap(r, l);
        }
        swap(end, l);
        return l;
    }

    static void swap(int f, int end) {
        int temp = a[f];
        a[f] = a[end];
        a[end] = temp;
    }

    public static void main(String[] args) {
        long t1=System.currentTimeMillis();
        int size = 100;
        a = new int[size];
        mid = (a.length - 1) / 2;// 这里可以选择自己想要的下标,得出的值就是第几大
        Random rand = new Random();
        for (int i = 0; i < size; i++) {
            int n = rand.nextInt(size * 5);
            a[i] = n;
        }
        finalsort();
        long t2=System.currentTimeMillis();
        System.out.println(t2-t1);
    }
}
第三个可以用做找出一个数组的第n大数据而不去排序它。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值