快速排序

找到分界点:

public static void sort(Comparable[] arr) {
    int n = arr.length;
    sort(arr, 0, n - 1);
}

private static void sort(Comparable[] arr, int l, int r) {
    if (l >= r) {
        return;
    }
    int p = partition(arr, l, r);
    sort(arr, l, p - 1);
    sort(arr, p + 1, r);
}

private static int partition(Comparable[] arr, int l, int r) {
    Comparable v = arr[l];
    int j = l;
    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;
}

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

高级排序在需要排列的数据量很小的时候,可以用插入排序优化

存在的问题: 当测试用例为近乎有序的数组时,以上排序方法会退化为n^2的算法,结果无法接受。优化办法是:在patition方法内选择分界元素时,不要指定arr[l],而是采用随机的方式得到,这样从概率的角度可以论证,复杂度为O(nlogn)。

需要继续优化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];
    // arr[l+1...i) <= v; arr(j...r] >= v
    int i = l+1, j = r;
    while( true ){
        // 注意这里的边界, arr[i].compareTo(v) < 0, 不能是arr[i].compareTo(v) <= 0
        while( i <= r && arr[i].compareTo(v) < 0 )
            i ++;

        // 注意这里的边界, arr[j].compareTo(v) > 0, 不能是arr[j].compareTo(v) >= 0
        while( j >= l+1 && arr[j].compareTo(v) > 0 )
            j --;

        if( i > j )
            break;

        swap( arr, i, j );
        i ++;
        j --;
    }
    swap(arr, l, j);
    return j;
}

results matching ""

    No results matching ""