算法讲解 快速排序

快速排序

在解决普通的排序问题时,我们通常使用的是较为简单的排序算法,但是这些简单的排序算法是存在一些问题的,比如我们常用的选择排序。

int a[N];
for(int i=0;i<n;i++)
{
  for(int j=i;j<n;j++)
    if(a[i]>a[j])swap(a[i],a[j]);
}

我们可以看出,这里书写了一个嵌套的循环,那么就可知在执行这段代码时的时间复杂度为O(n^2)。
那么倘若我们需要进行计算的数据量非常大的时候呢?那样我们所需要的计算时间就比较长了。而为了解决这个问题,我们可以学习其他的排序算法。
首先我们先学习快速排序。下图为快速排序的模板。

const int N=100010;
int a[N];
void sort(int left,int right)
{
  if(left>=right)return;
  int le=left-1,ri=right+1,mid=a[left+right>>1];
  while(le<ri)
  {
   do le++;while(a[le]<mid);
   do ri--;while(a[ri]>mid);
   if(le<ri)swap(a[le],a[ri]);
  }
  sort(left,ri),sort(ri+1,right);
  return;
}

由以上代码我们可以计算快速排序的时间复杂度。
首先可知
T ( n ) = O ( 1 ) ( n = 1 ) T ( n ) = 2 T ( n / 2 ) + c n ( n > 1 ) T(n)=O(1) (n=1)\\ T(n) =2T(n/2)+cn(n>1)\\ T(n)=O(1)(n=1)T(n)=2T(n/2)+cn(n>1)
由此可推
T ( n ) = 2 T ( n / 2 ) + c n = 2 2 T ( n / 2 2 ) + 2 c n = 2 3 T ( n / 2 3 ) + 3 c n . . . . . . . . . = 2 k T ( n / 2 k ) + k c n = n T ( 1 ) + k c n = n O ( 1 ) + k c n = n + c n l o g 2 n = n ( 1 + c l o g 2 n ) = O ( n l o g 2 n ) T(n) =2T(n/2)+cn\\ =2^{2}T(n/2^{2})+2cn\\ =2^{3}T(n/2^{3})+3cn\\ .........\\ =2^{k}T(n/2^{k})+kcn\\ =nT(1)+kcn\\ =nO(1)+kcn\\ =n+cnlog_2n\\ =n(1+clog_2n)\\ =O(nlog_2n) T(n)=2T(n/2)+cn=22T(n/22)+2cn=23T(n/23)+3cn.........=2kT(n/2k)+kcn=nT(1)+kcn=nO(1)+kcn=n+cnlog2n=n(1+clog2n=O(nlog2n)

通过上述过程我们计算出快速排序的时间复杂度为O(nlogn)。时间复杂度要小于选择与冒泡等基础的排序方法。
接下了我们举一个简单的例子来讲快速排序的逻辑过程。
例如一串数字
2 3 5 6 4 7
首先我们确定这串数组的左右边界。左端点位2,右端点位7。然后确定一个中间点(并不一定是中间值,只要是数组中的一个数字即可)我们选择5。
然后从左端开始2小于5向右移一位,
然后3小于5继续向右移动,直到所在位置的值大于5停止。(这时左指针在6的位置)。
然后判断右端指针,指向的数值为7大于5向左移动
然后4小于5停止。(这时右指针指向4)
现在左指针所在位置的下标小于右指针所指向的下标,交换这两个位置的数值。这时数字为
2 3 5 4 6 7
重复上述操作,知道左指针所在位置的下标大于等于右指针所指向的下标结束操作。
结束操作时数字为
2 3 5 4 6 7
然后以左端点以及使右指针为右端点为
2 3 5 4
重复之前的操作。
同时以右端点以及使右指针加一的位置为左端点为
6 7
重复之前的操作。最后即可得到正确的顺序。

上诉数字所有过程的序列为

2 3 5 6 4 7
2 3 5 4 6 7
(2 3 4 5) (6 7)
2 3 4 5 6 7

萌新书写,不清晰的地方多多见谅,欢迎交流。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值