本文中的代码适用于对数组元素进行排序(以整型数据为例)。
自定义的方法
在排序方法之前,定义了三个不同的方法,以便于对数组元素进行比较和交换。为了适用于不同的数据类型,这里使用到了 void 指针以及指针类型的转换,也就是 C 语言中范型的概念。如果需要对不同元素类型的数组进行排序,只修改 LessArr() 方法和 Less() 方法即可。
// 比较整型数组中两个元素的大小
int LessArr(void *arr, int i, int j, int size)
{
return *(int*) (arr + i * size) < *(int*) (arr + j * size);
}
// 比较两个整型元素的大小
int Less(void *x, void *y)
{
return *(int*) x < *(int*) y;
}
// 交换数组中元素的方法
void Exch(void *arr, int i, int j, int size)
{
void * temp = malloc(size);
memcpy(temp, arr + i * size, size);
memcpy(arr + i * size, arr + j * size, size);
memcpy(arr + j * size, temp, size);
free(temp);
}
未改进的快速排序
基本快速排序
基本快速排序的切分方法中,针对于切分的标志元素(这里是数组的首元素),通过自身与数组中其他元素不断交换位置来达到切分目的。
// 基本快速排序的切分方法
int Partation_Basic(void *arr, int lo, int hi, int size)
{
int v = lo;
--lo;
++hi;
while (1)
{
while (LessArr(arr, v, --hi, size)) if (hi == v) break;
if (lo >= hi) break;
Exch(arr, hi, v, size);
v = hi;
while (!LessArr(arr, v, ++lo, size)) if (lo == v) break;
if (lo >= hi) break;
Exch(arr, lo, v, size);
v = lo;
}
return v;
}
// 基本快速排序的双参方法
void QuickSort_Basic_Part(void *arr, int lo, int hi, int size)
{
if (lo >= hi) return;
int k = Partation_Basic(arr, lo, hi, size);
QuickSort_Basic_Part(arr, lo, k - 1, size);
QuickSort_Basic_Part(arr, k + 1, hi, size);
}
// 基本快速排序的单参方法
void QuickSort_Basic(void *arr, int len, int size)
{
QuickSort_Basic_Part(arr, 0, len - 1, size);
}
后交换快速排序
后交换快速排序同样是使用了很多次交换方法,不过对于基本快速排序来说,交换次数明显减少。因为切分的标志元素总是在大循环结束之后进行的,也就是说在前面的交换里,没有将自身加进来,这样就达成了使用更少的交换次数得到同样效果的目的。
// 后交换快速排序的切分方法
int Partation_Smart(void *arr, int lo, int hi, int size)
{
int i = lo, j = hi + 1;
void * v = malloc(size);
memcpy(v, arr + lo * size, size);
while (1)
{
while (!Less(v, arr + (++i) * size)) if (i == hi) break;
while (!Less(arr + (--j) * size, v)) if (j == lo) break;
if (i >= j) break;
Exch(arr, i, j, size);
}
Exch(arr, lo, j, size);
free(v);
return j;
}
// 后交换快速排序的双参方法
void QuickSort_Smart_Part(void *arr, int lo, int hi,