快速排序及其优化(JAVA)

1.Java代码实现

public class QuickSort {

    /**
     * 选择一个哨兵节点,将所有小于哨兵节点的元素放到左边,大于哨兵节点的元素放到右边
     * 最后将哨兵节点和小部分中的最右边那个值交换(j),i就处于大部分的最左边
     * @param array 数组元素
     * @param low
     * @param high
     */
    public static void quickSort(Integer[] array,int low,int high){
        if(low>=high){
            return;
        }
        int index = divide(array,low,high);
        quickSort(array,low,index-1);
        quickSort(array,index+1,high);
    }

    private static int divide(Integer[] array,int low,int high){
        int i = low+1, j = high;
        while(i<=j){
            while(i<=j&&array[i]<=array[low]){
                i++;
            }
            while(i<=j&&array[j]>array[low]){
                j--;
            }
            if(i<=j) {
                int k = array[j];
                array[j] = array[i];
                array[i] = k;
            }
        }
        int t = array[low];
        array[low] = array[j];
        array[j] = t;
        return j;
    }
}

2.优化策略(三数选中+插入+聚集)

由于一般哨兵节点都选取最左边或最右边的元素,容易造成时间复杂度为O(N*N)的情况(原数组有序),通过选取三个数(一般可以是最左元素,中间元素,最右元素)中的中间那个数来作为哨兵节点可以减少发生最坏的情况。
在元素个数比较少的情况下,插入排序要由于快排,所以在划分元素足够少的情况下,可以通过插入排序来进行排序。
同时在第一次遍历时,将重复元素聚集在一起,可以减少迭代次数。

public class QuickSort {

    /**
     * @param array 数组元素
     * @param low
     * @param high
     */
    public static void quickSort(Integer[] array,int low,int high){
        if(low>=high){
            return;
        }
        selectPivotMedianOfThree(array,low,high);
        int index = divide(array,low,high);
        int i = index-1,j = index+1;

        //聚集
        int ii = i,jj = j;
        while(ii>=low){
            if(array[index].equals(array[ii])){
                swap(array[ii],array[i]);
                i--;
            }
            ii--;
        }
        while(jj<=high){
            if(array[index].equals(array[jj])){
                swap(array[jj],array[j]);
                j++;
            }
            jj++;
        }

        if(i-low < 10){
            insertSort(array,low,i);
        }else {
            quickSort(array, low, i);
        }
        if(high-j < 10){
            insertSort(array,j,high);
        }else {
            quickSort(array, j, high);
        }
    }

    private static int divide(Integer[] array,int low,int high){
        int i = low+1, j = high;
        while(i<=j){
            while(i<=j&&array[i]<=array[low]){
                i++;
            }
            while(i<=j&&array[j]>=array[low]){
                j--;
            }
            if(i<=j) {
                swap(array[i],array[j]);
            }
        }
        swap(array[low],array[j]);
        return j;
    }

    //三数选中
    private static void selectPivotMedianOfThree(Integer[] array,int low,int high){
        int m = (low+high)/2;
        //实现 array[mid] <= array[low] <= array[high]
        if(array[high] < array[low]){
            swap(array[high],array[low]);
        }
        if(array[high] < array[m]){
            swap(array[high],array[m]);
        }
        if(array[m] > array[low]){
            swap(array[m],array[low]);
        }
    }

    //插入排序
    private static void insertSort(Integer[] array,int low,int high){
        for(int i = low+1; i < high; i++){
            Integer da = array[i];
            int j = i - 1;
            for(; j >= low; j--){
                if(array[j] <= da){
                    break;
                }
                array[j+1] = array[j];
            }
            array[j+1] = da;
        }
    }

    private static void swap(Integer a, Integer b){

        int tem= a;
        Field field= null;
        try {
            field = Integer.class.getDeclaredField("value");
            field.setAccessible(true);
            field.setInt(a, b);
            field.setInt(b, tem);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值