C/C++中有一个快速排序的标准库函数 qsort ,在stdlib.h 中声明,其原型为:
void qsort(void *base, int nelem, unsigned int width, int ( * pfCompare)( const void *, const void *));
使用该函数,可以对任何类型的一维数组排序。该函数参数中,base 是待排序数组的起始地址,nelem 是待排序数组的元素个数,width 是待排序数组的每个元素的大小(以字节为单位),最后一个参数 pfCompare 是一个函数指针,它指向一个“比较函数”。
修改排序数组排序起始基地址和带排序元素个数可以实现数组部分排序。
qsort 函数的用法规定,“比较函数”的原型应是:int 函数名(const void * elem1, const void * elem2);该函数的两个参数,elem1 和elem2,指向待比较的两个元素。也就是说, * elem1 和* elem2 就是待比较的两个元素。该函数必须具有以下行为:
1) 如果 * elem1 应该排在 * elem2 前面,则函数返回值是负整数(任何负整数都行)。
2) 如果 * elem1 和* elem2 哪个排在前面都行,那么函数返回0
3) 如果 * elem1 应该排在 * elem2 后面,则函数返回值是正整数(任何正整数都行)。
例如:
1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 using namespace std; 6 7 int compare(const void *a, const void *b) 8 { 9 int *pa = (int*)a; 10 int *pb = (int*)b; 11 return (*pa )- (*pb); //从小到大排序 12 } 13 14 void main() 15 { 16 int a[10] = {5, 6, 4, 3, 7, 0 ,8, 9, 2, 1}; 17 qsort(a, 10, sizeof(int), compare); 18 for (int i = 0; i < 10; i++) 19 cout << a[i] << " " << endl; 20 }
如果要从大到小排列,只需要将比较函数中return (*pa )- (*pb); 改为return (*pb )- (*pa); 即可。
再如:
下面的程序,功能是调用qsort 库函数,将一个unsigned int 数组按照个位数从小到大进行排序。比如 8,23,15 三个数,按个位数从小到大排序,就应该是 23,15,8:
1 #include <stdio.h> 2 #include <stdlib.h> 3 int MyCompare( const void * elem1, const void * elem2 4 { 5 unsigned int * p1, * p2; 6 p1 = (unsigned int *) elem1; //语句6 7 p2 = (unsigned int *) elem2; //语句7 8 return (* p1 % 10) - (* p2 % 10 ); //语句8 9 } 10 #define NUM 5 11 int main() 12 { 13 unsigned int an[NUM] = { 8,123,11,10,4 }; 14 qsort( an, NUM, sizeof(unsigned int), MyCompare); 15 for( int i = 0;i < NUM; i ++ ) 16 printf("%d ", an[i]); 17 return 0; 18 }
上面程序的输出结果是:
10 11 123 4 8
qsort 函数执行期间,需要比较两个元素哪个应在前面时,就以两个元素的地址作为参数,调用 MyCompare 函数。如果返回值小于0,则qsort 就得知第一个元素应该在前,如果返回值大于0,则第一个元素应该在后。如果返回值等于0,则哪个在前都行。
对语句6 解释如下:由于elem1 是 const void * 类型的,是void 指针,那么表达式“*elem1”是没有意义的。elem1 应指向待比较的元素,即一个unsigned int 类型的变量,所以要经过强制类型转换,将elem1 里存放的地址赋值给 p1,这样,* p1 就是待比较的第
一个元素了。语句7 同理。语句8 体现了排序的规则。如果 *p1 的个位数小于 *p2 的个位数,那么就返回负值。其他两种情况不再赘述。