快速排序算法

算法的一般思想:

快速排序算法有两个核心点,分别为 “哨兵划分” 和 “递归” 。

哨兵划分操作: 以数组某个元素(一般选取首元素)为 基准数 ,将所有小于基准数的元素移动至其左边,大于基准数的元素移动至其右边。

如下图所示,为哨兵划分操作流程。通过一轮 哨兵划分 ,可将数组排序问题拆分为 两个较短数组的排序问题 (本文称之为左(右)子数组)。

递归: 对 左子数组 和 右子数组 递归执行 哨兵划分,直至子数组长度为 1 时终止递归,即可完成对整个数组的排序。

如下图所示,为示例数组 [2,4,1,0,3,5] 的快速排序流程。观察发现,快速排序和 二分法 的原理类似,都是以 log⁡\loglog 时间复杂度实现搜索区间缩小。

我对它的理解:

帮助每个子区间(用递归)的首元素(哨兵)找到它在这个区间(按照某种排序方式后的位置,这里为从小到大)应有的位置,因为此时这个位置 i,它左边所有的元素都比它小,右边的元素都比它大,但左边和右边仍然是无序的,所以需要继续使用递归帮助除了位置 i 的子区间的首元素找到各自应有的位置。

class Solution {
    //帮助每个子区间的第一个元素(哨兵)找到它在这个区间应有的位置,因为此时
    // 它左边所有的元素都比它小,右边的元素都比它大,那它现在
    // 所处的位置就是它按照从小到大后应在的位置

    private static void quickSort(int[] arr, int l, int r) {
        if (l >= r) return; //这个区间只有一个元素了,根本不需要找它的位置了
        int i = l, j = r; 
        /*然后第一个元素作为标准,就是所谓的
        哨兵元素,一般都习惯以第一个元素作为哨兵*/
        while (i < j) {
            while (i < j && arr[j] >= arr[l]) l--;
            while (i < j && arr[i] <= arr[l]) i++;
            swap(arr, i, j); 
            }
            /*遇到了不符合“从小到大”的排序规则的元素就进行交换
       i,j相遇了,说明已经排好序了*/
        swap(arr, i, l);
        /*此时,除了哨兵元素之外,因为arr[i]是比arr[l]小的
         且i+1一个元素后就比arr[l]大了,所以i需要和l交换,便
         可得到哨兵元素应有的位置 i*/

        quickSort(arr,l,i-1);
        quickSort(arr,i+1,r);
    }

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

复杂度

复杂度分析:
时间复杂度 O(Nlog⁡N)O(N \log N)O(NlogN) : 库函数、快排等排序算法的平均时间复杂度为 O(Nlog⁡N)O(N \log N)O(NlogN) 。
空间复杂度 O(N)O(N)O(N) : 快速排序的递归深度最好(平均)为 O(log⁡N)O(\log N)O(logN) ,最差情况(即输入数组完全倒序)为 O(N)O(N)O(N)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值