思路
选主元,什么是主元,就是在待排序的元素中找一个元素,可以把元素分为两边,一边比主元大,一边比主元小,然后递归排序地去解决两边的元素。这个元素就叫做主元,简单粗暴的理解。随机利用rand函数随机选择的方法就不说了。
中位数法,把最左边,最中间,最右边的三个数的中间值作为主元
代码
//qsort-1-2.c
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#define MAXN 100
typedef int ElementType;
void Swap(int *X,int *Y)
{
int tmp = *X;
*X = *Y;
*Y = tmp;
}
void InsertionSort(ElementType A[], int N)
{
int i = 0;
for(int P=1;P<N;P++) {
int Tmp = A[P];
for(i = P;i>0 && A[i-1] > Tmp;i--)
A[i] = A[i-1];
A[i] = Tmp;
}
}
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 */
}
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 ); /* 元素太少,用简单排序 */
}
void QuickSort( ElementType A[], int N )
{ /* 统一接口 */
Qsort( A, 0, N-1 );
}
void Print_Array(ElementType A[],int N)
{
for(int i=0;i<N;i++){
printf("%d ",A[i]);
if((i+1)%5==0) printf("\n");
}
}
int main()
{
int a[MAXN];
srand(time(NULL));//保证乱序
for (int i = 0; i < MAXN; i++)
a[i] = rand()%(1000)+1; /*随机数产生[1,1000]范围之间的随机数*/
QuickSort(a,MAXN);
Print_Array(a,MAXN);
return 0;
}
总结
1.体现了分而治之的思想,最坏时间复杂度O(N^2)
2.因为采用递归,小规模数据不适宜采用快速排序,利用选择排序就差不多行了,随着要排序的数量不断增大,大规模数据考虑用快速排序