快速排序

(一) 简介:

快速排序是一种基于分治思想的算法,
分治,顾名思义,就是划整为零,将大问题化分成一系列类似的小问题,解决各个小问题后,再进行结果整合,求出大问题的解。

(二)整体算法结构描述:

QuickSort(A, p, r)
    int q = Partition(A, p, r);  //先对大问题进行划分,划分成两个问题
    QuickSort(A, p, q);          //针对两个规模稍小的问题集,再去求解
    QuickSort(A, q+1, r);


(三)Partition分割过程描述:

Partition(A, p, r)功能:将数组A[p......r]划分成三部分:
1. 确定主元:pivot用来进行分割的元素
2. A[p......q]  这组元素都小于pivot
3. A[q+1......r] 这组元素都大于等于pivot
再分别对A[p......q]和A[q+1......r]分别进行快速排序,最终得到一个全局有序的数组 在对分割后的问题求解时,会继续划分,直至问题可以直接求解而无需分解,即递归出口:当p = r,即求解的问题规模为1的时候。

 


(四)Partition分割示意图:

快速排序_第1张图片

 

[p......i]范围内存放的是小于Pivot的元素
[i+1......j]存放的是大于等于pivot的元素
[j+1......r]存放还未处理的元素
若A[j]大于等于pivot,j++;
若A[j]小于pivot,则i++; exchange A[j] <->A[i]; j++
在处理过程中始终保持上图中的结构

 


(五)Partition代码实现:

/**********************************************************
函数名:Partition
功能:以pSrcData[r]作为pivot,将数组进行分割,使得
pSrcData[p....q-1] <= pSrcData[q]
pSrcData[q+1....r] > pSrcData[q]
参数:[in] pSrcData 数据缓冲区首指针
     [in] p 数组开始下标
     [in] r 数组结束下标
返回值:pivot的位置
***********************************************************/
int Partition(int* pSrcData, int p, int r)
{
     if (p == r)    return p;
     int pivot = pSrcData[r]; //以最后一个元素作为分割主元
     int i = p - 1;

     for (int j = p; j < r; j++)
     {
          if (pSrcData[j] < pivot)
          {
              i++;

               if ( i != j)
               {
                   int nTmp = pSrcData[j];
                   pSrcData[j] = pSrcData[i];
                   pSrcData[i] = nTmp;
               }
          }
    }

    int nRightFirstIndex = i + 1;
    pSrcData[r] = pSrcData[nRightFirstIndex];
    pSrcData[nRightFirstIndex] = pivot;

    return nRightFirstIndex;
}

 

(六)快速排序实现:

/**********************************************************
函数名:QuickSort
功能:快速排序
参数:[in] pSrcData 数据缓冲区首指针
          [in] p 缓冲区开始下标
          [in] r  缓冲区结束下标
返回值:无
***********************************************************/
void QuickSort(int* pSrcData, int p, int r)
{
    if (p >= r) return;

    int q = Partition(pSrcData,  p,  r);
    QuickSort(pSrcData, p, q-1);
    QuickSort(pSrcData, q+1, r);
}


(七)程序结果:


快速排序_第2张图片
说明:每一个分割线都是一次递归~用红框标出的就是pivot,每一次都是用最后一个元素作为pivot,第二排中的小红框为分割后pivot的新位置。

(八)复杂度分析:

1.最坏情况考虑:

就是对n个数据进行排序时,工作量最大的情况。 
那就是进行切割后几乎没啥效果。啥意思,打个比方: 
对于数组A[1......n],切割时选择的是最小元素作为主元pivot,那么比pivot小的没有,A[2......N]全比pivot大。
对A[2......n]进行切割,效果也是同上述的类似。
那么在递归是,每一次对主元左边的元素排序时无效的,因为没有元素比主元小!
所以第一次切割要做n-1次比较
第二次切割要做n-2次比较
.......
最后一次切割要做1次比较. (n-1 + n-2 + ...... +1) = (n-1)*n/2; 复杂度是O(n2);

 

2.良好情况:

每次切割时都能均匀分配,切割后主元左边的元素和主元右边的元素数量相对平衡

可以这样写:T(n) = 2T(n/2) + O(n); 为了简化,就这样写吧: T(n) = 2T(n/2) + cn; c为常数

在简化一下,n是2的m次幂

T(n) = 2T(n/2) + cn

       = 2 (2T(n/4) + cn/2) + cn = ...... 2^m * T(1) + m*cn ;

已知: T(1) = 0; 2^m = n;

推出:T(n) = m*cn = cn * lgn

复杂度为O(nlgn);

 

注:1. 这边在分析复杂度时做了一些简化,但是不影响大局
       2. 这个编辑器对于输入一些数学公式时貌似不是很方便

你可能感兴趣的:(算法,快速排序,alogrithm)