QuickSort 快速排序算法

引子:快速排序算法,被列为 20 世纪 十大算法之一。
希尔排序相当于直接插入排序的升级,只是增加了increment的设置,利用了基本有序的思想,同属于插入排序类。堆排序相当于简单选择排序的升级,他们同属于选择排序类,只是通过构建堆(完全二叉树)的方式,让选择最大项更加快速。而快速排序其实就是我们前面认为最慢的冒泡排序的升级,他们同属于交换排序类。即它也是通过不断比较和移动交换来实现排序的,不过它的实现,增大了记录的比较和移动的距离,将关键字较大的记录从前面直接移动到后面,关键字较小的记录从后面直接移动到前面,从而减小了比较次数和移动交换次数。

基本思想:(Quick Sort )通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。

代码:
/* 对顺序表 L 作快速排序 */
void QuickSort( SqList *L )
{
     QSort( L, 1, L->length );
}


/* 对顺序表 L 中的子序列 L->r[low...high]作快速排序 */
void QSort( SqList *L, int low, int high )
{
     int pivot;
     if( low < high )     //递归条件出口
     {
          pivot = Partition(L, low, high);     /* 将L->r[low...high]一分为二 */
                                                       /* 算出枢纽值 pivot */
          QSort(L, low, pivot-1);
          QSort(L, pivot+1, high);
     }
}

/* 交换顺序表 L 中子表的记录,使枢轴记录到位,并返回其交换后所在位置 */
/* 此时在之前(后)的记录均不大(小)于它。 */
int Partition(SqList *L, int low, int high)
{
     int pivotkey;
     pivotkey = L->r[low];
     while(low < high)
     {
          while( low < high && L->r[high] >= pivotkey )     /* 从high往左找,找到一个比 pivotkey小的元素 */
               high--;
          swap(L, low, high );     /* 右小 左大 互换 */
          while(low < high && L->r[low] <= pivotkey )          /* 从low往右找,找到一个比pivotkey大的元素 */
               low++;
          swap(L, low, high);          /* 左大 右小 互换 */
     }
     /* 最后结束循环,low 与 high 相等,返回low,返回位置 */
     return low;

复杂度
时间复杂度 o(n log n)
空间复杂度 o(log n)

优化:
1. 优化选取枢纽(三数取中、九数取中),上述代码中,枢纽选择都是第一个元素,如果是最大或者最小元素,则会成为单只树。
2. 优化不必要的交换(将 pivotkey 被分到 L.r[0]中,然后是swap时,只做替换的工作,最终当 low 与 high 会和,即找到了枢轴的位置时,再将L.r[0] 的数值 赋值回 L.r[low]),因此减少了多次交换数据的操作。
3. 优化小数组时的排序方案(小数组时候,选用直接插入排序,快排对小数组排序没有优势,可能还要慢于最简单的插入排序)
4. 优化递归操作(对QSort实施尾递归优化,减小递归深度,提高效率)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值