408数据结构之快速排序
快速排序
关于快速排序,408试卷中多为选择题,考察手动模拟快速排序过程,特别是对”划分一次子集,就有一个元素确定最终位置“这一特点的考察,2016年出现了涉及快速排序思想的数据结构大题,可见深入理解其思想和算法的必要性。
1、主流辅导书写法
列出《王道》和《天勤》的写法,更加推荐看王道上的算法。
1)王道数据结构
王道书的写法来自严蔚敏的《数据结构》,主元直接选择待排集合中的第一个元素,通俗易懂,便于理解快速排序算法的本质,但是在划分子集的时候有多余的比较,选主元pivot也简单选择第一个元素,存在极端情况时间复杂度为O(N2),有提升空间(应试的话掌握到这里就足够了)。
void QuickSort(ElemType A[],int low,int high){
if(low<high){ //结束递归条件
int pivotpos=Partiton(A,low,high); //选主元,划分子集
QuickSort(A,low,pivotpos-1); //递归处理主元两侧的子集
QuickSort(A,pivotpos+1,high);
}
}
int Partiton(ElemType A[],int low,int high){
ElemType pivot=A[low]; //选取集合中第一个元素为主元
while(low<high){
while(low<high&&A[high]>=pivot) --high; //从右开始找小于主元的元素
A[low]=A[high]; //换到左面
while(low<high&&A[low]<=pivot) ++low; //从左开始找大于主元的元素
A[high]=A[low]; //换到右面
}
A[low]=pivot; //循环结束时,low=high, 也就是主元的最终位置
return low; //返回主元的最终位置
}
2)天勤数据结构
天勤书上的算法就不推荐看了,既不便理解快速排序的本质,在性能上有没有实质上的提升。
void QuickSort(int R[],int low,int high){
int temp;
int i=low,j=high;
if(low<high){
temp=R[low];
while(i<j){
while(j>i&&R[j]>=temp) --j;
if(i<j){
R[i]=R[j];
++i;
}
while(i<j&&R[j]<=temp) ++i;
if(i<j){
R[j]=R[j];
--j;
}
}
R[i]=temp;
QuickSort(R,low,i-1);
QuickSort(R,i+1,high);
}
}
2、浙江大学《数据结构》慕课给出算法
推荐这门慕课,感谢陈越姥姥和何钦铭老师的付出~
https://www.icourse163.org/course/ZJU-93001?tid=1461682474
看完这个算法就想说”老程序员了“,考虑到了几点实际应用的细节:
1、统一函数接口;
2、引入阈值Cutoff,快速排序属于递归算法,且不适宜处理基本有序的集合,引入Cutoff以后就可以视数据规模调整处理方法;
3、主元pivot选取集合中头、中、尾三个数的中值,有效的避免了处理原本就有序的集合所出现的极端情况,选取函数设计的非常合理,调用完以后同时将划分子集的规模也减小2,算法的额外开销微乎其微。
4、划分子集时,采用一次交换两边的元素,比每次把一边的元素换到另一边的做法更加高效。
void QuickSort( ElementType A[], int N )
{ /* 统一接口 */
Qsort( A, 0, N-1 );
}
void Qsort( ElementType A[], int Left, int Right )
{ /* 核心递归函数 */
int Pivot, Cutoff, Low, High;
if ( Cutoff <= Right-Left ) { /* 如果序列元素充分多,进入快排 */
Pivot = Median3( A, Left, Right ); /* 选基准 */
Low = Left; High = Right-1;
while (1) { /*将序列中比基准小的移到基准左边,大的移到右边*/
while ( A[++Low] < Pivot ) ;
while ( A[--High] > Pivot ) ;
if ( Low < High ) Swap( &A[Low], &A[High] );
else break;
}
Swap( &A[Low], &A[Right-1] ); /* 将基准换到正确的位置 */
Qsort( A, Left, Low-1 ); /* 递归解决左边 */
Qsort( A, Low+1, Right ); /* 递归解决右边 */
}
else InsertionSort( A+Left, Right-Left+1 ); /* 元素太少,用简单排序 */
}
ElementType Median3( ElementType A[], int Left, int Right )
{
int Center = (Left+Right) / 2;
if ( A[Left] > A[Center] )
Swap( &A[Left], &A[Center] );
if ( A[Left] > A[Right] )
Swap( &A[Left], &A[Right] );
if ( A[Center] > A[Right] )
Swap( &A[Center], &A[Right] );
/* 此时A[Left] <= A[Center] <= A[Right] */
Swap( &A[Center], &A[Right-1] ); /* 将基准Pivot藏到右边*/
/* 只需要考虑A[Left+1] … A[Right-2] */
return A[Right-1]; /* 返回基准Pivot */
}

浙公网安备 33010602011771号