单路快速排序

单路快速排序的时间复杂度为O(nlog2n),空间复杂度为O(n)

单路快速排序的核心思想:选取一个标定元素,将数组二分(一般为非等分),保证左侧部分比标定元素小,右侧部分比标定元素大,即将标定元素放到该元素在数组中应该在的位置,如下图所示:

排序的过程和示意图如下:

  1. 随机选择一个位置的元素与数组首元素交换位置,作为标定元素V,此操作可以有效避免快速排序在排序近乎有序的数组时,退化为时间复杂度为O(n^2)的算法
  2. 从第二个元素开始,找到第一个比标定元素V大的元素,位置记为j+1,即j是已排序数组中最后一个比V小的元素。此操作可以提高近乎有序数组快排的效率
  3. 此时开始递归排序,如果新加入的元素大于等于标定元素V,则直接加入排序数据,并且i++
  4. 如果新加入的元素比V小,则j++,并且交换swap(arr[j], arr[i]),然后i++
  5. 直到排序所有元素,然后交换wap(arr[j], arr[L]),至此完成排序

代码如下:

template<typename T>
void quickSort(T arr[], int n) {
    srand(time(nullptr));
    _quickSort(arr, 0, n - 1);
}

// 对arr[rangeL,rangeR]部分进行快速排序
template<typename T>
void _quickSort(T arr[], int rangeL, int rangeR) {
    if (rangeL >= rangeR) {
        return;
    }
    if (rangeR - rangeL <= 16) {
        insertionSort(arr, rangeL, rangeR);
        return;
    }

    int index = _quickPartition(arr, rangeL, rangeR);

    _quickSort(arr, rangeL, index - 1);
    _quickSort(arr, index + 1, rangeR);
}

// 对arr[rangeL,rangeR]部分进行_quickPartition操作
// 返回index, 使得arr[rangeL, index - 1] < arr[index] ; arr[index + 1, rangeR] > arr[index]
template<typename T>
int _quickPartition(T arr[], int rangeL, int rangeR) {
    // 优化点:随机在arr[rangeR, rangeL]的范围中, 选择一个数值作为标定点pivot
    swap(arr[rangeL], arr[rand() % (rangeR - rangeL + 1) + rangeL]);

    T temp = arr[rangeL];
    int j = rangeL;

    //优化点:首先找出第一个大于arr[rangeL],从该值开始排序,能提升基本有序数组的排序效率
    for (int i = rangeL + 1; i <= rangeR; i++) {
        if (arr[i] >= temp) {
            j = i - 1;
            break;
        }
    }

    for (int i = rangeL + 1; i <= rangeR; i++) {
        if (arr[i] < temp) {
            j++;
            swap(arr[i], arr[j]);
        }
    }

    swap(arr[j], arr[rangeL]);
    return j;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值