qsort(即quick sort)是C语言中的一个标准库函数,用于对数组进行快速排序。它是一种高效的排序算法,具有较好的平均和最坏情况下的时间复杂度。
qsort函数的声明如下:
void qsort(void* base, size_t nmemb, size_t size, int (compar)(const void, const void*));
参数解释如下:
base:指向要排序的数组的第一个元素的指针。
nmemb:数组中元素的数量。
size:每个元素的大小(以字节为单位)。
compar:指向比较函数的指针,用于定义元素之间的排序顺序。
比较函数compar用于定义元素之间的排序顺序,它接收两个指向元素的指针,通常为 void* 类型。比较函数需要返回一个整数值,代表两个元素的大小关系:
如果返回值小于0,表示第一个元素应该排在第二个元素之前。
如果返回值等于0,表示两个元素相等。
如果返回值大于0,表示第一个元素应该排在第二个元素之后。
使用qsort函数,可以对各种类型的数组进行排序,包括整型、浮点型、字符型以及自定义结构体等。
我们刚刚了解到了,对于排序不同类型的数据,需要自定义不同的compar函数,接下来看一下整形的例子
#include
#include
// 比较函数,用于升序排序
int compare(const void* a, const void* b) {
return (*(int*)a - *(int*)b);
}
int main() {
int arr[] = {5, 2, 8, 1, 9, 3};
int size = sizeof(arr) / sizeof(arr[0]);
qsort(arr, size, sizeof(int), compare);
printf("升序排序结果:");
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
接下来就直接只展示不同类型的数据compare函数
int cmp_float(const void* e1, const void* e2)
{
return (int)(*(float*)e1 - *(float*)e2);
}
int cmp_str_size(const void* e1, const void* e2)
{
return strcmp((char*)e1, (char*)e2);
}
int cmp_by_name(const void* e1, const void* e2)
{
return (int)(((stu*)e1)->age - ((str*)e2)->age);
}
上述结构体排序是年龄,接下来我们来比较结构体中按中文名字排序
#include
#include //使用qsort函数需要包含头文件
#include
struct stu
{
char name[20];
int age;
};
int cmp_name(const void* e1, const void* e2)
{
return strcmp(((struct stu*)e1)->name , ((struct stu*)e2)->name);
}
int main()
{
struct stu arr[3] = { {"张三", 20}, {"李四", 18}, {"王五", 36} };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_name);
for (int i = 0; i < sz; i++)
{
printf("%s %d ", arr[i].name, arr[i].age);
printf("\n");
}
return 0;
}
了解了qsort函数的使用,我们来尝试模拟一下qsort函数的实现
#include
void swap(char* p1, char* p2, int width)
{
for (int i = 0; i < width; i++) //不知道是什么类型,所以要一个字节一个字节来进行交换
{
char temp = *p1;
*p1 = *p2;
*p2 = temp;
p1++;
p2++;
}
}
int compare(const void* p1, const void* p2)
{
return *((int*)p1) - *((int*)p2);
}
//void* base - 要求排序不同类型的数组,void*恰好能接收任意类型的数据
//int num - 元素个数
//int width - 一个元素的大小
//int (*compare)(const void* p1, const void* p2) 函数传参函数指针接收
int my_qsort(void* base, int num, int width,int (*compare)(const void* p1, const void* p2)))
{
for (int i = 0; i < num - 1; i++)
{
for (int j = 0; j < num - 1 - i; j++)
{
//强制类型转化为char*型的数据,是因为一开始不知道数组的类型
//如果要访问数据的话,只能一个字节一个字节的访问
//这样有利于排序各种类型的数
if (compare((char*)base + j * width,(char*)base + (j + 1) * width) > 0)
{
//写一个Swap函数来交换
swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
}
}
}
}
int print(int arr[], int num)
{
for (int i = 0; i < num; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
int arr[10] = { ![11,23,54,65,87,34,59,55,66,44]
int num = sizeof(arr) / sizeof(arr[0]);//计算数组中的元素个数
//打印排序前的数组
printf("排序前为:");
print(arr, num);
printf("\n");
my_qsort(arr, num, sizeof(arr[0]), compare);
//打印排序后的数组
printf("排序后为:");
print(arr, num);
return 0;
}