vlambda博客
学习文章列表

基础算法(一)快速排序

  • 算法思想

  通过一个分界值x,将序列分为大于x和小于x的两部分(注意,此分界值不一定是在序列中点,而是随便选取),然后再递归处理这左右两部分,直到x左边的值都小于等于x,x右边的值都大于等于x,这样我们就得到了一个排好序的有序序列。


  • 代码模板

 

void quick_sort(int l,int r) //对q数组区间[l,r]的序列排序{ if(l>=r) return; //若l==r,区间长度为1,则返回 int x=q[l+r>>1],i=l-1,j=r+1; //设定分界值x(通常取两边或中点) //注意i,j初始值在两端点之外 while(i<j)  {  do i++;while(q[i]<x); //一直在左边找,直到找到大于等于x的数 do j--;while(q[j]>x); //一直在右边找,直到找到小于等于x的数 if(i<j) swap(q[i],q[j]); //交换这两个数,这样一来刚刚大于等于x的数就跑到右边了,小于等于x的数就跑到左边了 } quick_sort(l,j); //递归左右两边序列 quick_sort(j+1,r);}
  • 时间复杂度分析

   

快速排序的一次划分算法从两头交替搜索,直到l和r重合,因此其时间复杂度是O(n);而整个快速排序算法的时间复杂度与划分的趟数有关。
理想的情况是,每次划分所选择的中间数恰好将当前序列几乎等分,经过log 2n趟划分,便可得到长度为1的子表。这样,整个算法的时间复杂度为O(nlog 2n)。

最坏的情况是,每次所选的中间数是当前序列中的最大或最小元素,这使得每次划分所得的子表中一个为空表,另一子表的长度为原表的长度-1。这样,长度为n的数据表的快速排序需要经过n趟划分,使得整个排序算法的时间复杂度为O(n 2)。