5分钟回忆快速排序

快排

  • 任务描述
  • 算法思路
    • 如何瞎选
    • 怎么丢来丢去
      • 坑位法
      • 交换法
  • 复杂度分析
    • 最好情况
    • 最坏情况

任务描述

在这里插入图片描述

给我从小到大排序!!!

算法思路

 首先“瞎选”一个值,找到其最终位置,即排好序后它在哪,并把小于它的丢左边,大于的丢右边。对左右子部分重复操作,直至子部分都只剩一个元素,则所有元素都找到了其该在的位置。
5分钟回忆快速排序_第1张图片
5分钟回忆快速排序_第2张图片

如何瞎选

第一个?
如果数组正好是从大到小的,那我每一轮都要撸(比较) n n n个数才能找到选的数应该在哪,撸 n n n轮,实现过程相当与变成了选择排序(先把一个数丢最后面,再第二个…),复杂度 O ( n 2 ) O(n^2) O(n2)
生成随机数?
有意思嘛,本来就要减少运行时间,还要用代码去生成随机数,浪费时间。
简单做法
取中间的数,无所谓了,反正要随机,去算一组数的中值更麻烦。

怎么丢来丢去

过程中得把小的丢左边,大的丢右边,怎么实现呢,难道另申请一个数组小的从前往后存,大的从后往前存?浪费空间!肯定动的是原数组,以下通过选6作为第一轮基准值来说明

坑位法

既然要对原数组变动,则需要留一个坑位来避免数据丢失,不然变动了值后面要用怎么办,谁做第一个坑呢,当然是基准值的位置!先备份6,然后从头开始遍历数组,一旦发现有比选中数6大的,比如第3个数7,把它丢到6的位置,这时候第3个数7已经没用了,不怕被覆盖,成为了新的坑位;然后从尾开始遍历数组,一旦发现有比选中数7小的,比如3,把3丢到新的坑位即将第三个数复制为3;然后从4四个数开始往后遍历…直到遍历完整个数组,完成第一轮!下图红色圈代表坑位
5分钟回忆快速排序_第3张图片

交换法

一样的思路,从头开始遍历,一旦发现有大的数停一下,然后从后遍历,一旦发现有小的数,立刻交换这两个数,免去了坑位…
ps:得注意角标问题,可以各后退一步

复杂度分析

最好情况

每次找的正好是中值,则除了加上这次耗费n次比较才找到自己的位置,还加上子部分的复杂度。最后结果为 O ( n l o g n ) O(nlogn) O(nlogn)
T ( n ) = { 1 , n=1 2 T ( n 2 ) + n , n>1 T(n) = \begin{cases} 1, & \text{n=1} \\ 2T(\frac{n}{2})+n, & \text{n>1} \end{cases} T(n)={1,2T(2n)+n,n=1n>1
T ( n ) = 2 ( 2 T ( n 2 2 ) + n 2 ) + n = 2 2 T ( n 2 2 ) + 2 n = 3 3 T ( n 2 3 ) + 3 n = 2 log ⁡ 2 n + n log ⁡ 2 n = n l o g ( n ) \begin{aligned} T(n) &=2(2T(\frac{n}{2^2})+\frac{n}{2})+n\\&=2^2T(\frac{n}{2^2})+2n\\&=3^3T(\frac{n}{2^3})+3n\\&=2^{\log_2 n}+n\log_2 n\\&=nlog(n) \end{aligned} T(n)=2(2T(22n)+2n)+n=22T(22n)+2n=33T(23n)+3n=2log2n+nlog2n=nlog(n)

最坏情况

即瞎选第一个,且数组倒叙的情况,复杂度 O ( n 2 ) O(n^2) O(n2)

你可能感兴趣的:(算法,算法,数据结构,排序算法,快速排序)