qsort函数的功能与使用
qsort
是C标准库中提供的快速排序函数,强大的点在于其可以对任意类型的数组进行排序。核心优势在于通过回调函数实现泛型排序,适用于各种数据类型。
函数定义如下:
void qsort( void *base, //指向待排序的数组
size_t num, //待排序的个数
size_t width, //待排序的元素大小
int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
//提供的比较方式
- base 指向待排序的数组首元素地址
- sum 数组中元素个数
- width 单个元素的字节大小
- compare 比较函数的指针(需要自己定义)
- 若需要将数组按照升序排列,当elem1>elem2时候返回大于0的值,反之则反
使用实例:
假设现在有一个无序的整数数组,需要对其按照升序排序
#include <stdlib.h>
#include <stdio.h>
int compare_int(const void* a, const void* b) {
return (*(int*)a - *(int*)b);
}//自定义的compare 适用于int类型
int main() {
int arr[] = {5, 2, 9, 1, 5};
qsort(arr, 5, sizeof(int), compare_int);
for (int i = 0; i < 5; i++) printf("%d ", arr[i]);
// 输出:1 2 5 5 9
}
针对不同数据类型
以下示例展示了如何定制比较函数,覆盖常见数据类型。每个示例都使用qsort
进行排序,并输出结果。
示例1: 整数类型(int)
使用减法直接比较,但需注意整数溢出风险(对于大数)。建议优先使用比较运算符(如<
或>
)以避免问题。
#include <stdlib.h>
#include <stdio.h>
int compare_int(const void* a, const void* b) {
int int_a = *(const int*)a;
int int_b = *(const int*)b;
if (int_a < int_b) return -1;
if (int_a > int_b) return 1;
return 0;
// 或者简化版(但有溢出风险): return (*(int*)a - *(int*)b);
}
int main() {
int arr[] = {5, 2, 9, 1, 5};
size_t num = sizeof(arr) / sizeof(arr[0]);
qsort(arr, num, sizeof(int), compare_int);
for (size_t i = 0; i < num; i++) printf("%d ", arr[i]); // 输出: 1 2 5 5 9
}
示例2: 浮点数类型(double)
浮点数比较涉及精度问题,不能直接使用减法(因为减法可能受浮点误差影响)。
#include <stdlib.h>
#include <stdio.h>
int compare_double(const void* a, const void* b)
{
double double_a = *(const double*)a;
double double_b = *(const double*)b;
if (double_a < double_b)
return -1;
if (double_a > double_b)
return 1;
return 0;
}
int main()
{
double arr[] = { 3.14, 1.59, 2.65, 0.01 };
size_t num = sizeof(arr) / sizeof(arr[0]);
qsort(arr, num, sizeof(double), compare_double);
for (size_t i = 0; i < num; i++)
printf("%.2f ", arr[i]); // 输出: 0.01 1.59 2.65 3.14
}
示例3: 字符串类型(char)*
字符串比较不能使用减法,需调用strcmp
函数(来自<string.h>
)strcmp
直接返回所需的负数、零或正数。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int compare_string(const void* a, const void* b)
{
const char* str_a = *(const char**)a; // 注意:数组元素是char*,所以需解引用为指针的指针
const char* str_b = *(const char**)b;
return strcmp(str_a, str_b);
}
int main()
{
const char* arr[] = { "apple", "banana", "cherry", "date" };
size_t num = sizeof(arr) / sizeof(arr[0]);
qsort(arr, num, sizeof(char*), compare_string);
for (size_t i = 0; i < num; i++)
printf("%s ", arr[i]); // 输出: apple banana cherry date
}
示例4: 结构体类型(struct)
结构体排序通常基于某个字段(如id或name)。比较函数需提取字段值进行比较。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
int id;
char name[20];
} Person;
int compare_person_by_id(const void* a, const void* b)
{
const Person* person_a = (const Person*)a;
const Person* person_b = (const Person*)b;
if (person_a->id < person_b->id)
return -1;
if (person_a->id > person_b->id)
return 1;
return 0;
}
int compare_person_by_name(const void* a, const void* b)
{
const Person* person_a = (const Person*)a;
const Person* person_b = (const Person*)b;
return strcmp(person_a->name, person_b->name);
}
int main() {
Person arr[] = { {3, "Alice"}, {1, "Bob"}, {2, "Charlie"} };
size_t num = sizeof(arr) / sizeof(arr[0]);
// 按id排序
qsort(arr, num, sizeof(Person), compare_person_by_id);
printf("按id排序: ");
for (size_t i = 0; i < num; i++)
printf("%d:%s ", arr[i].id, arr[i].name); // 输出: 1:Bob 2:Charlie 3:Alice
// 按name排序
qsort(arr, num, sizeof(Person), compare_person_by_name);
printf("\n按name排序: ");
for (size_t i = 0; i < num; i++)
printf("%d:%s ", arr[i].id, arr[i].name); // 输出: 3:Alice 1:Bob 2:Charlie
}
需要注意的是,compare函数中的返回值,对于数值类型,减法虽然简便,但是需警惕溢出问题或者精度问题。其次,在强制转换指针时,确保类型匹配。