快速排序优化


快速排序又叫快排、思路是找一个元素作为pivot、我们选取最后的元素作为pivot、从数组首位开始遍历、将小于pivot的放在数组前面的位置、最后将pivot放在两个分区的中间、pivot的右边的元素都大于pivot、左边的元素都小于pivot、这就分好了两个区域、然后继续对两个区域分区–>指定pivot、交换元素、分区…直到分区只有一个元素的时候也就都有序了。
时间复杂度为log2n、但是最坏的情况下也会变为O(n²):假设数组是有序的、那么每次找的pivot都是数组中最大的元素、那么每次都要将数组遍历完、时间复杂度就会变成O(n²)、那么我们可以对此做出优化、每次取pivot的时候、找出三个数、找出三个数中间的数作为pivot、也可以随机数选取pivot来分区。
三向切分法优化、假设数组中的重复的元素比较多的话:我们假设第一次选取的pivot在数组中存在多个重复的、那么将与pivot相同的元素都排在了pivot的前面、pivot之前的元素已经是有序的了、那么就没有必要继续对pivot之前的元素继续分区了。那么我们可以做出优化、将数组分为三个区域、小于pivot 的区域、等于pivot的区域、大于pivot的区域、下次分区的时候只分小于pivot的、和大于pivot的区域即可。

原始的写法

class Sort {
    public static void main(String[] args) {
        int[] array = {23, 434, 577, 8, 9, 91, 6, 2, 1};
        quickSort(array);
        System.out.println(Arrays.toString(array));
        ;
    }

    public static void quickSort(int[] array) {
        sort(array, 0, array.length - 1);
    }

    public static void sort(int[] array, int low, int high) {
        if (low >= high) {
            return;
        }
        int par = partition(array, low, high);
        sort(array, low, par - 1);
        sort(array, par + 1, high);
    }

    public static int partition(int[] array, int low, int high) {
        int pivot = array[high];
        int less = low;
        int great = low;
        
        for (; great < high; great++) {
            if (array[great] < pivot) {
                int tmp = array[less];
                array[less] = array[great];
                array[great] = tmp;
                less++;
            }
        }

        int tmp = array[high];
        array[high] = array[less];
        array[less] = tmp;

        return less;
    }
}

随机数法优化

    public static void swap(int[] array, int index1, int index2) {
        int tmp = array[index1];
        array[index1] = array[index2];
        array[index2] = tmp;
    }
    public static void quickSort(int[] array) {
        sort(array, 0, array.length - 1);
    }

    public static void sort(int[] array, int low, int high) {
        if (low >= high) {
            return;
        }
        int par = partition(array, low, high);
        sort(array, low, par - 1);
        sort(array, par + 1, high);
    }

    public static int getPivotIndex(int[] array, int low, int high) {
        return new Random().nextInt(high - low) + low;
    }

    public static int partition(int[] array, int low, int high) {
        //随机数法:
        int index = getPivotIndex(array,low,high);
        //将随机数与最右边的元素交换、也就是之前的排序
        swap(array,high,index);
        int pivot = array[high];
        int less = low;
        int great = low;

        for (; great < high; great++) {
            if (array[great] < pivot) {
                swap(array,less,great);
                less++;
            }
        }

        swap(array,less,high);

        return less;
    }

三向切分法优化

class ThreeWaySort{
    public static void main(String[] args) {
        int[] array = {34,42,2,133,766,64,43};
        quicksort(array);
        System.out.println(Arrays.toString(array));
    }
    public static void quicksort(int[] array){
        sort(array,0,array.length-1);
    }

    public static void sort(int[] array,int low,int high){
        if (low >= high){
            return;
        }

        int pivot = array[high];
        int less = low;
        int great = high;
        int i = low;
        while (i <= great){
            if (array[i] < pivot){
                swap(array,i,less);
                less++;
                i++;
            } else if (array[i] > pivot){
                swap(array,i,great);
                great--;
                i++;
            } else {
                i++;
            }
        }

        sort(array,low,less-1);
        sort(array,great+1,high);
    }

    public static void swap(int [] array,int index1,int index2){
        int tmp = array[index1];
        array[index1] = array[index2];
        array[index2] = tmp;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值