高级排序 04 快速排序 随机版

本文介绍了一种改进的基础快速排序算法——随机化快速排序。通过在partition方法中随机选择标定点,解决了基础版在处理近乎有序数组时效率低下的问题。实测表明,随机化快速排序在处理大规模数据时,比归并排序有常数级优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码实现

  • 相比于基础版的快速排序,随机化的快速排序的改动在于 partition(Comparable[] arr, int l, int r) 方法;
  • 基础版在选择 v 的时候,永远选择第1个元素,在近乎有序的数组中,就是n * n的遍历;
  • 随机版在选择 v 的时候,从 arr 中任选一个来,换到第一个位置去,算法其余部分不变,从而可以较好的解决近乎有序的数组的问题;
public class QuickSort {

    // 我们的算法类不允许产生任何实例
    private QuickSort(){}

    // 对arr[l...r]部分进行partition操作
    // 返回p, 使得arr[l...p-1] < arr[p] ; arr[p+1...r] > arr[p]
    private static int partition(Comparable[] arr, int l, int r){

        // 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivot
        swap(arr, l, (int)(Math.random() * (r - l + 1)) + l);

        Comparable v = arr[l];

        int j = l; // arr[l+1...j] < v ; arr[j+1...i) > v
        for( int i = l + 1 ; i <= r ; i ++ )
            if( arr[i].compareTo(v) < 0 ){
                j ++;
                swap(arr, j, i);
            }

        swap(arr, l, j);

        return j;
    }

    // 递归使用快速排序,对arr[l...r]的范围进行排序
    private static void sort(Comparable[] arr, int l, int r){

        // 对于小规模数组, 使用插入排序
        if( r - l <= 15 ){
            InsertionSort.sort(arr, l, r);
            return;
        }

        int p = partition(arr, l, r);
        sort(arr, l, p-1 );
        sort(arr, p+1, r);
    }

    public static void sort(Comparable[] arr){

        int n = arr.length;
        sort(arr, 0, n-1);
    }

    private static void swap(Object[] arr, int i, int j) {
        Object t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }

    // 测试 QuickSort
    public static void main(String[] args) {

        // Quick Sort也是一个O(nlogn)复杂度的算法
        // 可以在1秒之内轻松处理100万数量级的数据
        int N = 1000000;
        Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000);
        SortTestHelper.testSort("bobo.algo.QuickSort", arr);

        return;
    }

}

测试代码

import java.util.Arrays;

public class Main {

    // 比较Merge Sort和Quick Sort两种排序算法的性能效率
    // 两种排序算法虽然都是O(nlogn)级别的, 但是Quick Sort算法有常数级的优势
    // Quick Sort要比Merge Sort快, 即使我们对Merge Sort进行了优化
    public static void main(String[] args) {

        int N = 1000000;

        // 测试1 一般性测试
        System.out.println("Test for random array, size = " + N + " , random range [0, " + N + "]");

        Integer[] arr1 = SortTestHelper.generateRandomArray(N, 0, N);
        Integer[] arr2 = Arrays.copyOf(arr1, arr1.length);

        SortTestHelper.testSort("_03.sorting_advanced._06.quick_sort_random.MergeSort", arr1);
        SortTestHelper.testSort("_03.sorting_advanced._06.quick_sort_random.QuickSort", arr2);

        System.out.println();


        // 测试2 测试近乎有序的数组
        // 加入了随机选择标定点的步骤后, 我们的快速排序可以轻松处理近乎有序的数组
        // 但是对于近乎有序的数组, 其效率比优化后的归并排序要低, 但完全再容忍范围里
        // 思考一下为什么对于近乎有序的数组, 快排的性能比优化后的归并排序低? :)
        int swapTimes = 100;
        assert swapTimes >= 0;

        System.out.println("Test for nearly ordered array, size = " + N + " , swap time = " + swapTimes);

        arr1 = SortTestHelper.generateNearlyOrderedArray(N, swapTimes);
        arr2 = Arrays.copyOf(arr1, arr1.length);

        SortTestHelper.testSort("_03.sorting_advanced._06.quick_sort_random.MergeSort", arr1);
        SortTestHelper.testSort("_03.sorting_advanced._06.quick_sort_random.QuickSort", arr2);

        System.out.println();
    }

}

输出:

Test for random array, size = 1000000 , random range [0, 1000000]
MergeSort : 442ms
QuickSort : 323ms

Test for nearly ordered array, size = 1000000 , swap time = 100
MergeSort : 87ms
QuickSort : 88ms
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值