快速排序是一种基于分治思想的算法,
分治,顾名思义,就是划整为零,将大问题化分成一系列类似的小问题,解决各个小问题后,再进行结果整合,求出大问题的解。
QuickSort(A, p, r) int q = Partition(A, p, r); //先对大问题进行划分,划分成两个问题 QuickSort(A, p, q); //针对两个规模稍小的问题集,再去求解 QuickSort(A, q+1, r);
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的时候。
[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 功能:以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); }
每次切割时都能均匀分配,切割后主元左边的元素和主元右边的元素数量相对平衡
可以这样写: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. 这个编辑器对于输入一些数学公式时貌似不是很方便