void qsort(
void *base, //接收所要排序的目标数组名
size_t num, //接收排序数组的个数(以元素为单位)
size_t width, //每一个元素大小(以字节为单位)
int (__cdecl *compare )(const void *elem1, const void *elem2 ) //自定义的比较方法
);
这里要注意qsort函数里的void* , 这里一旦写成其他类型都会只能对一种数据类型排序,而空类型void*正好可以接收其他任何类型,从而当做参数!
自定义比较函数
这里MSDN上给出了一些关于该函数的说明,具体大家可以自行查看
参数类型:
int compare( const void * elem1,const void * elem2 );
int arr[] = {
1,3,4,8,2,6,7,5,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_int);
那么这里也就是第一个参数小于第二个参数的话返回值 < 0;
第一个参数大于第二个参数的话返回值 > 0;
第一个参数等于第二个参数的话返回值 = 0;
int cmp_int(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2;
}
对传进来的e1和e2用void* 来接收,并且考虑到使用的时候是对整型数组排序,因此强转成int * ,
用e1-e2,e1 > e2,返回值大于0,e1 < e2,返回值小于0,e1 = e2,返回值等于0,满足要求。
完整代码:
#include
#include
int cmp_int(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2;
}
int main()
{
int arr[] = {
1,3,4,8,2,6,7,5,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_int);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
int cmp_int(const void* e1, const void* e2)
{
return *(int*)e2 - *(int*)e1;
}
#include
#include
int cmp_char(const void* e1, const void* e2)
{
return *(char*)e1 - *(char*)e2;
}
int main()
{
char a[] = {
'a','c','e','d','b' };
int sz = sizeof(a) / sizeof(a[0]);
qsort(a, sz, sizeof(a[0]), cmp_char);
for (int i = 0; i < sz; i++)
{
printf("%c ", a[i]);
}
return 0;
}
#include
#include
int cmp_double(const void* e1, const void* e2)
{
return ((*(double*)e1 - *(double*)e2) > 0)? 1:-1;
}
int main()
{
double a[] = {
1.2,56.4,0.56,456.89,32.4 };
int sz = sizeof(a) / sizeof(a[0]);
qsort(a, sz, sizeof(a[0]), cmp_double);
for (int i = 0; i < sz; i++)
{
printf("%.2f ", a[i]);
}
return 0;
}
#include
#include
int cmp_string(const void* e1, const void* e2)
{
return strcmp((char*)e1, (char*)e2);
}
int main()
{
char a[5][6] = {
"h","he","hel","hell","hello" };
int sz = sizeof(a) / sizeof(a[0]);
qsort(a, sz, sizeof(a[0]), cmp_string);
for (int i = 0; i < sz; i++)
{
printf("%s ", a[i]);
}
return 0;
}
struct student
{
char name[20];
int age;
};
这里我们定义了一个结构体,那么接下来按照名字和年龄两种排序情况说明
1. 按照name排序
#include
#include
struct student
{
char name[20];
int age;
};
int cmp_name(const void* e1, const void* e2)
{
return strcmp(((student*)e1)->name, ((student*)e2)->name);
}
void test()
{
student s[3] = {
{
"z",15},{
"l",17},{
"w",20} };
qsort(s, sizeof(s) / sizeof(s[0]), sizeof(s[0]), cmp_name);
for (int i = 0; i < 3; i++)
{
printf("%s ", s[i].name);
}
}
int main()
{
test();
return 0;
}
2. 按照年龄排序:
#include
#include
struct student
{
char name[20];
int age;
};
int cmp_age(const void* e1, const void* e2)
{
return ((student*)e1)->age - ((student*)e2)->age;
}
void test1()
{
student s[3] = {
{
"张三",15},{
"李四",17},{
"王伟",20} };
Bubble_sort(s, sizeof(s) / sizeof(s[0]), sizeof(s[0]), cmp_age);
for (int i = 0; i < 3; i++)
{
printf("%s ", s[i].name);
}
}
int main()
{
test1();
return 0;
}
这里我们采用冒泡排序来实现qsort函数:
void Bubble_sort(void* base, size_t num, size_t width, int(* compare)(const void* elem1, const void* elem2))
{
for (size_t i = 0; i < num; i++)//冒泡排序的趟数
{
for (size_t j = 0; j < num - 1 - i;j++)//每一趟
{
//判断交换
}
}
}
void Bubble_sort(void* base, size_t num, size_t width, int(* compare)(const void* elem1, const void* elem2))
{
for (size_t i = 0; i < num; i++)//冒泡排序的趟数
{
for (size_t j = 0; j < num - 1 - i;j++)//每一趟
{
if (compare((char*)base+j*width,(char*)base+(j+1)*width) > 0)
{
Swap((char*)base + j * width, (char*)base + (j + 1) * width,width);
}
}
}
}
完整代码:
void Swap(char* buffer1, char* buffer2,int width)
{
for (int i = 0; i < width; i++)
{
char t = *buffer1;
*buffer1 = *buffer2;
*buffer2 = t;
buffer1++;
buffer2++;
}
}
void Bubble_sort(void* base, size_t num, size_t width, int(* compare)(const void* elem1, const void* elem2))
{
for (size_t i = 0; i < num; i++)//冒泡排序的趟数
{
for (size_t j = 0; j < num - 1 - i;j++)//每一趟
{
if (compare((char*)base+j*width,(char*)base+(j+1)*width) > 0)
{
Swap((char*)base + j * width, (char*)base + (j + 1) * width,width);
}
}
}
}
void myqsort(void * base, size_t nitems, size_t size, int(*compar)(const void *, const void *))
{
int i, j;
char * st = (char *)base; //void *不方便加减,用char *加减轻松且字节跳转为1,方便控制。
char tmp[16]; //考虑到long double类型,临时空间做成16字节比较保险
for (i = 0; i < nitems - 1; i++)
{
for (j = 0; j < nitems - 1 - i; j++) //冒泡常用循环头
{
if (compar(st + j * size, st + (j + 1) * size)) //比较的时候跳转注意乘size
{
memcpy(tmp, st + j * size, size); //交换操作用memcpy完成就不会出问题。
memcpy(st + j * size, st + (j + 1) * size, size);
memcpy(st + (j + 1) * size, tmp, size);
}
}
}
}