void qsort(void* base,
size_t num,
size_t width,
int (*compar)(const void* e1, const void* e2));
base:待排序的数据的起始位置,为了能够对所有类型的数据进行排序,base 的类型被设置为 void*。
num:待排序的数据元素的个数。size_t 为无符号整形。
width:待排序的数据元素的大小。
compar:函数指针,指向一个比较函数,compar 函数的实现形式需要程序员自己实现。
引用头文件
#include
int (*compar)(const void* e1, const void* e2)
确定函数的返回值
1. 比较整型数据
int cmp_int(const void* e1, const void* e2)
{
return (*(int*)e1 - *(int*)e2);//返回两个数强转后的差值
}
2. 比较浮点型数据
int cmp_float(const void* e1, const void* e2)
{
return (int)(*(float*)e1 - *(float*)e2);//需要先将结果强转为 int 再返回
}
3. 比较字符型数据
int cmp_char(const void* e1, const void* e2)
{
return (int)(*(char*)e1 - *(char*)e2);
}
4. 比较结构体变量
int cmp_by_age(const void*e1, const void*e2)
{
return (int)(((stu*)e1)->结构体成员 - ((stu*)e2)->结构体成员);
}
5. 比较字符串大小
int cmp_str_size(const void* e1, const void* e2)
{
return strcmp((char*)e1,(char*)e2);
}
6. 比较其他类型数据
整型排序
#include
#include
int cmp_int(const void* e1, const void* e2)
{
return (*(int*)e1 - *(int*)e2);//e1 - e2 是排成升序,e2 - e1 是排成降序
}
int main()
{
int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
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]);
}
putchar('\n');
return 0;
}
浮点型排序
#include
#include
int cmp_float(const void* e1, const void* e2)
{
return (int)(*(float*)e1 - *(float*)e2);//e1 - e2 是排成升序,e2 - e1 是排成降序
}
int main()
{
float arr[] = { 5.0,4.0,3.0,2.0,1.0 };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_float);//需要自己提供比较函数
for (int i = 0; i < sz; i++)
{
printf("%.1f ", arr[i]);
}
putchar('\n');
return 0;
}
结构体排序
#include
#include
#include
struct S
{
int age;
char name[20];
};
int cmp_by_name(const void* e1, const void* e2)//按照姓名排序
{
return strcmp(((struct S*)e1)->name, ((struct S*)e2)->name);
}
int cmp_by_age(const void* e1, const void* e2)//按照年龄排序
{
return (((struct S*)e1)->age - ((struct S*)e2)->age);
}
int main()
{
struct S s[] = { {18,"zhangsan"},{19,"lisi"},{20,"wangwu"}};
int sz = sizeof(s) / sizeof(s[0]);
qsort(s, sz, sizeof(s[0]), cmp_by_name); //按照姓名成员进行排序
//qsort(s, sz, sizeof(s[0]), cmp_by_age); //按照年龄成员进行排序
for (int i = 0; i < sz; i++)
{
printf("%d %s\n", s[i].age, s[i].name);
}
return 0;
}
void Swap(char* buf1, char* buf2, int width)
{
//交换 buf1 和 buf2 指向的元素的向后 width 个字节的内容
for (int i = 0; i < width; i++)
{
char tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
void bubble_sort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
{
int i = 0;
int j = 0;
for (i = 0; i < sz - 1; i++)
{
int flag = 1;
for (j = 0; j < sz - 1 - i; j++)
{
//用比较函数进行比较,不再用 <> 号比较
//传给 cmp 相当于 base[j] 和 base[j + 1] 的地址;
//将指针强转为 char*,确保向后访问的最小字节数;
//然后让 j 或 j + 1 去 * width 确定指针每次 +1 时向后访问 width 个字节
if (cmp(((char*)base + j * width), (char*)base + (j + 1) * width) > 0)
{
//交换
Swap(((char*)base + j * width), (char*)base + (j + 1) * width, width);
//传过去这两个元素的起始地址,以及这两个元素的宽度,将这两个元素的每一个字节都进行交换
flag = 0;
}
}
if (flag)//这一趟没有进行任何交换操作,就没必要继续浪费时间了
{
break;
}
}
}
#include
int cmp_int(const void* e1, const void* e2)
{
return (int)(*(int*)e1 - *(int*)e2);
}
void Swap(char* buf1, char* buf2, int width)
{
//交换 buf1 和 buf2 指向的元素的向后 width 个字节的内容
for (int i = 0; i < width; i++)
{
char tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
void bubble_sort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
{
int i = 0;
int j = 0;
for (i = 0; i < sz - 1; i++)
{
int flag = 1;
for (j = 0; j < sz - 1 - i; j++)
{
//用比较函数进行比较,不再用 <> 号比较
//传给 cmp 相当于 base[j] 和 base[j + 1] 的地址;
//将指针强转为 char*,确保向后访问的最小字节数;
//然后让 j 或 j + 1 去 * width 确定指针每次 +1 时向后访问 width 个字节
if (cmp(((char*)base + j * width), (char*)base + (j + 1) * width) > 0)
{
//交换,> 0 要排成升序
Swap(((char*)base + j * width), (char*)base + (j + 1) * width, width);
//传过去这两个元素的起始地址,以及这两个元素的宽度,将这两个元素的每一个字节都进行交换
flag = 0;
}
}
if (flag)//这一趟没有进行任何交换操作,就没必要继续浪费时间了
{
break;
}
}
}
int main()
{
int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
putchar('\n');
return 0;
}