数据结构学习(十三)、快速排序

基本思想:通过一趟排序将待排记录分割成独立两个部分,其中一部分记录的关键字均比另一部分记录的关键字小,

则可分别对这两部分继续进行排序,重复操作以上操作,已达到整个序列有序的目的

void QuickSort(SqList *L)
 {
    QSort(L,1,L->length);
 }
/* 对顺序表L中的子序列L->dara[low..high]最快速排序 */
 void QSort(SqList *L,int low,int high)
 {
    int pivot;
    if(low<high){
        pivot = Partition(L,low,high);        /*将L->data[low..high]一分为二,并算出分界点 */
        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 --;
        swap(L,low,high);
        while(low<high && L->r[low]<=pivotkey)
            low++;
        swap(L,low,high);
    }
    return low;
 }

 改进算法:

1、优化选取枢轴

  三数取中法,即先选取三个关键字进行排序,将中间数作为枢轴,一般取左端、中间、右端三个数。


/*
交换L中子表的记录,使枢轴记录到位,并返回其所在的位置
此时,它之前(后)的记录均不大(小)于它
*/
 int Partition(SqList *L,int low,int high)
 {
    int pivotkey;
    int m = low +(high-low)/2;            /* 计算数组中间元素的下标 */
    if(L->data[low]>L->data[high])      /* 交换左右保证左边的较小 */
         swap(L,low,high);
     if(L->data[m]>L->data[high])      /* 交换中间 和右边保证中间的较小 */
         swap(L,m,high);
     if(L->data[low]>L->data[m])      /* 交换中间 和左边保证左边的较小 */
         swap(L,m,low);
    pivotkey = L->data[m];                   /* 用子表的中间值作为枢轴 */
     L->data[0] = pivotkey;                     /* 将轴关键字备份到L->data[0] */
    while(low<high){
        while(low<high && L->data[high]>=pivotkey)
            high --;
        L->data[low] = L->data[high];        /* 采用替换 而不采用交换 */
        while(low<high && L->data[low]<=pivotkey)
            low++;
        L->data[high] = L->data[low];         /* 采用替换 而不采用交换 */
    }
    L->data[low] = L->data[0];                /* 将枢轴数值替换回L->data[low] */
    return low;
 }


 

优化不必要的交换

原文地址:https://www.cnblogs.com/huixuexidezhu/p/5969200.html