一、回调函数
在讲qsort函数之前我们先得熟悉一下回调函数,看到回调函数这个名词有些小伙伴可能觉得有点陌生,其实他就是通过函数指针调用的函数。不太清楚函数指针的朋友可以看看我之前写的博客,链接在下方。http://t.csdnimg.cn/UNrMuhttp://深入探寻指针奥秘之"它们"与指针的爱恨情仇
回调函数:如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用作调用其所指向的函数时,被调用的函数就是回调函数。
#include <stdio.h>
// 定义回调函数的类型,它接受一个整数参数并返回一个整数
typedef int (*CallbackFunc)(int);
// 一个示例函数,它将使用回调函数来处理传入的整数
void processNumber(int number, CallbackFunc callback) {
int result = callback(number); // 调用回调函数
printf("Processed number: %d, result: %d\n", number, result);
}
// 回调函数示例,将输入的整数乘以2
int doubleNumber(int num) {
return num * 2;
}
// 另一个回调函数示例,将输入的整数加10
int addTen(int num) {
return num + 10;
}
int main() {
int number = 5;
// 使用processNumber函数并传递doubleNumber作为回调函数
processNumber(number, doubleNumber);
// 使用processNumber函数并传递addTen作为回调函数
processNumber(number, addTen);
return 0;
}
二、qsort函数说明
还是贴上cplusplus的网址!
函数总结:
-
参数说明:
base
: 指向要排序的数组的第一个对象的指针,转换为void*
类型。num
: 数组中的元素数量,使用size_t
类型,这是一个无符号整型。size
: 数组中每个元素的大小(以字节为单位),也使用size_t
类型。compar
: 一个比较函数的指针,qsort
会反复调用这个函数来比较两个元素。
-
比较函数 (
compar
):- 必须遵循特定的原型:
int compar(const void*, const void*);
- 接受两个
const void*
类型的参数,即指向要比较的两个元素的指针。 - 必须以稳定且可传递的方式返回以下值之一:
- 小于0:第一个参数指向的元素排在第二个之前。
- 等于0:两个元素等价。
- 大于0:第一个参数指向的元素排在第二个之后。
- 必须遵循特定的原型:
-
元素类型:
- 由于
qsort
使用void*
作为基础指针类型,它可以对任何类型的数组进行排序,只要提供了合适的比较函数。
- 由于
-
返回值:
qsort
不返回任何值,它直接修改base
指向的数组内容,重新排序其元素。
-
使用示例:
- 对于可以使用常规关系运算符比较的类型,可以编写一个通用的比较函数,如示例中的
compareMyType
函数。
- 对于可以使用常规关系运算符比较的类型,可以编写一个通用的比较函数,如示例中的
-
类型安全:
- 由于
qsort
使用void*
指针,调用者需要确保在调用比较函数时正确地将这些指针转换为适当的类型。
- 由于
-
内存分配:
- 调用
qsort
之前,必须确保数组已经被正确地分配和初始化。
- 调用
三、qsort函数使用
#include <stdio.h>
#include <stdlib.h>
// 定义一个整数比较函数,用于qsort的比较函数参数
int compareInts(const void* a, const void* b) {
// 将void指针转换为int*指针
const int* ia = (const int*)a;
const int* ib = (const int*)b;
// 如果第一个整数小于第二个,返回负数
if (*ia < *ib) return -1;
// 如果两个整数相等,返回0
if (*ia == *ib) return 0;
// 如果第一个整数大于第二个,返回正数
return 1;
}
int main() {
int arr[] = {5, 1, 9, 3, 7}; // 定义一个整数数组
int n = sizeof(arr) / sizeof(arr[0]); // 计算数组元素个数
int i;
// 使用qsort函数对数组进行排序
// 参数1: 指向数组的指针
// 参数2: 数组元素个数
// 参数3: 每个元素的大小(以字节为单位)
// 参数4: 比较函数的指针
qsort(arr, n, sizeof(arr[0]), compareInts);
// 打印排序后的数组
printf("Sorted array:\n");
for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
四、qsort模拟实现
#include<stdio.h>
#include<stdlib.h>
int int_cmp(const void* a, const void* b)
{
return (*(int*)a - *(int*)b);
}
void _swap(void* a, void* b,int size)
{
int i = 0;
for (i = 0; i < size; i++)
{
char temp = *((char*)a + i);
*((char*) a + i) = *((char*)b + i);
*((char*)b + i) = temp;
}
}
void bubble(void* base, int count, int size, int (*cmp)(void*, void*))
{
int i = 0;
int j = 0;
for (i = 0; i < count - 1; i++)
{
for (j = 0; j < count - i - 1; j++)
{
if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
{
_swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
}
}
}
}
int main()
{
int arr[] = { 1,3,5,7,9,2,4,6,8,0 };
int i = 0;
bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);
for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
代码详解:
-
比较函数
int_cmp
:int int_cmp(const void* a, const void* b) { return (*(int*)a - *(int*)b); }
这是一个比较两个整数的函数,它接受两个
void
类型的指针,将它们转换为int
类型指针,然后比较它们指向的整数值。如果a
指向的值小于b
指向的值,结果为负;如果相等,结果为0;如果a
指向的值大于b
指向的值,结果为正。 -
交换函数
_swap
:void _swap(void* a, void* b, int size) { int i; for (i = 0; i < size; i++) { char temp = *((char*)a + i); *((char*)a + i) = *((char*)b + i); *((char*)b + i) = temp; } }
这个函数用于交换两个内存位置的值。它接受两个
void
类型的指针和要交换的大小(以字节为单位)。通过逐字节交换,它实现了两个元素的值交换。 -
冒泡排序函数
bubble
:void bubble(void* base, int count, int size, int (*cmp)(void*, void*)) { int i, j; for (i = 0; i < count - 1; i++) { for (j = 0; j < count - i - 1; j++) { if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0) { _swap((char*)base + j * size, (char*)base + (j + 1) * size, size); } } } }
这个函数实现了冒泡排序算法。它接受一个指向数据的指针
base
、元素数量count
、每个元素的大小size
和一个比较函数指针cmp
。通过双重循环,它遍历数组,使用cmp
函数比较相邻元素,如果不符合排序条件,则使用_swap
函数交换它们的位置。
本期内容到此结束啦,如果对你有帮助的话点亮小星星把!