QuickSort 快速排序算法

来源:互联网 发布:ubuntu命令模式字体 编辑:程序博客网 时间:2024/04/30 21:17
引子:快速排序算法,被列为 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实施尾递归优化,减小递归深度,提高效率)



0 0
原创粉丝点击