快速排序

快速排序

顾名思义:快速排序是基于比较的排序算法中最快的一种–复杂度会更趋近于O(nlogn)

执行流程
  • 从序列中选择一个轴点(pivot)–假设每次选择0位置的元素为轴点元素
  • 利用pivotj将序列分割成2个子序列
    • 将小于pivot的元素放在pivot前面(左侧)
    • 将大于pivot的元素放在pivot后面(右侧)
    • 等于pivot的元素放那边都可以

就是帮第一个元素找到他对应的位置

  • 对子序列进行1, 2 操作
    • 递归操作
    • 直到不能再分割(子序列中只剩下一个元素)递归结束条件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Egtlcd8-1594791225498)(img\008_1.png)]

轴点构造

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7NrZwAk9-1594791225499)(img\008_2.png)]

  • 第一步: 将第一个元素存储(用它来构造轴点)
  • 从右开始比较,如果大于轴点元素则end指针向前移动一位,如果小于等于则用end指针的元素将begin位置覆盖并调转方向,开始移动begin
  • 类似第二步,移动begin
  • begin == end时,说明已经移动完成,该位置就为轴点元素的存放位置,此时将第一步保存的轴点元素存在在此
代码
/**
 * 对 [begin, end) 范围的元素进行快速排序
 * @param begin
 * @param end
 */
private void sort(int begin, int end) { 
    if (end - begin < 2) return; // 递归的结束条件

    // 确定轴点位置 O(n)
    int mid = pivotIndex(begin, end);
    // 对子序列进行快速排序
    sort(begin, mid); 
    sort(mid + 1, end); 
} 

/**
 * 构造出 [begin, end) 范围的轴点元素
 * @return 轴点元素的最终位置
 */
private int pivotIndex(int begin, int end) {
    // 随机选择一个元素跟begin位置进行交换
    swap(begin, begin + (int)(Math.random() * (end - begin)));

    // 备份begin位置的元素
    T pivot = array[begin];
    // end指向最后一个元素
    end--;

    while (begin < end) {
        while (begin < end) {
            if (cmp(pivot, array[end]) < 0) { // 右边元素 > 轴点元素
                end--;
            } else { // 右边元素 <= 轴点元素
                array[begin++] = array[end];
                break;
            }
        }
        while (begin < end) {
            if (cmp(pivot, array[begin]) > 0) { // 左边元素 < 轴点元素
                begin++;
            } else { // 左边元素 >= 轴点元素
                array[end--] = array[begin];
                break;
            }
        }
    }

    // 将轴点元素放入最终的位置
    array[begin] = pivot;
    // 返回轴点元素的位置
    return begin;
}

注意点:

// 随机选择一个元素跟begin位置进行交换
swap(begin, begin + (int)(Math.random() * (end - begin)));

可以直接使用第一个元素进行轴点构造,但是使用随机可以使用使构造更均匀–可以减小时间复杂度 (后面分析)

while () {
    while() {
        
    }
    while() {
        
    }
}
// 嵌套循环可以实现类似开关的作用
时间复杂度
  • 在轴点左右元素数量比较均匀的情况下,同时也是最好的情况

T(n) = 2 * T(n / 2) + O(n) = O(nlogn)

  • 如果轴点数量极度不均匀,最坏情况

T(n) = T(n - 1) + O(n) = O(n^2)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cA8wCaXE-1594791225501)(D:\algorithms\blog\algorithms\img\008_3.png)]

  • 为了降低最坏情况的出现概率,一般采取的做法是随机选择轴点元素
  • 最好,平均时间复杂度: O(nlogn)
  • 最坏时间复杂度:O(n^2)
  • 由于递归调用的缘故,空间复杂度O(logn)
  • 属于不稳定排序
补充

关于递归算法的复杂度分析建议阅读《算法导论》中关于递归地章节,确实很枯燥但是学完感觉对分析有很好的认识,里面包含的主方法,递归树,公式等的详细分析

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值