快排函数参数说明
qsort(s,n,sizeof(s[0]),cmp)
s
需要排序的数组名n
数组中元素的个数sizeof()
返回一个元素的 sizecmp
比较函数,具体见下文
比较函数
典型的比较函数定义是
int cmp(const void *a,const void *b)
其中,函数名 cmp 和参数名 a, b 都是可以自定义的,但类型必须是 const void *
型。
函数返回值必须是 int 型,如果需要结尾为升序,则在 a > b
的情况下返回正值,反之返回负值。
例如最常见的对 int 数组进行排序的比较函数写法如下:
int cmp(const void *a, const void *b) {
return (*(int *) a - *(int *) b);
}
对于 double 数组而言,由于两个 double 类型数不能直接判断相等,因此我们可以处理为只返回 1 和 -1,或者增加其他判断语句来返回0的情况,这里我们简单的作只返回 -1 和 1 作为例子:
int cmp(const void *a, const void *b) {
return ((*(double *) a - *(double *) b > 0) ? 1 : -1);
}
那么当需要对二维数组排序时,可以用如下代码实现,也可以直接定义为结构体,推荐后者。本代码中,如果第一维值相等,则继续比较第二维的大小,可以根据实际情况修改。
int cmp(const void *a,const void *b)
{
int *c = (int *)a;
int *d = (int *)b;
if(*c != *d)
return *c - *d;
return *(c+1) - *(d+1);
}
完整示例源码
#include <stdio.h>
#include <stdlib.h>
int s[10000], n, i;
int cmp(const void *a, const void *b) {
return (*(int *) a - *(int *) b);
}
int main() {
scanf("%d", &n);
for (i = 0; i < n; i++) scanf("%d", &s[i]);
qsort(s, n, sizeof(s[0]), cmp);
for (i = 0; i < n; i++) printf("%d ", s[i]);
return (0);
}
快排函数实现源码
void qsort(int a[], int low, int high) {
if (low >= high) {
return;
}
int first = low;
int last = high;
int key = a[first]; // 用字表的第一个记录作为枢轴
while (first < last) {
while (first < last && a[last] >= key) {
--last;
}
a[first] = a[last]; // 将比第一个小的移到低端
while (first < last && a[first] <= key) {
++first;
}
a[last] = a[first]; // 将比第一个大的移到高端
}
a[first] = key; // 枢轴记录到位
qsort(a, low, first - 1);
qsort(a, first + 1, high);
}
快排的不稳定性
快排是不稳定的,这个不稳定一个表现在其使用的时间是不确定的,最好情况 (O(n)) 和最
坏情况 (O(n^2)) 差距太大,我们一般说的 O(n·log(n)) 都是指的是其平均时间.快排是不稳定的,这个不稳定表现在如果相同的比较元素,可能顺序不一样,假设我们有
这样一个序列 3, 3, 3 但是这三个3是有区别的,我们标记为 3a, 3b, 3c 快排后的结果不一定就是 3a, 3b, 3c 这样的排列,所以在某些特定场合我们要用结构体来使其稳定。
关于快排的技巧
快排 qsort() 的第三个参数,推荐使用sizeof(s[0]),特别是对结构体,
往往自己定义2 * sizeof(int)
可能会出问题,用sizeof(s[0])
既方便又保险。如果要对数组进行部分排序,比如对一个 s[n] 的数组排列其从 s[i] 开始的 m 个元素,只需要
在第一个和第二个参数上进行一些修改,例如qsort(&s[i], m, sizeof(s[i]), cmp)
。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。