函数指针实例:使用冒泡排序模拟实现qsort的功能
程序员文章站
2023-12-26 17:25:57
...
qsort简介
qsort是函数库提供给我们的一种使用快速排序来实现各种类型数据排序的函数
功 能: 使用快速排序例程进行排序
头文件:stdlib.h或search.h
用 法:_CRTIMP void __cdecl qsort(void*, size_t, size_t,int (*)(const void*, const void*));
参数解释:
1 待排序数组首地址
2 数组中待排序元素数量
3 各元素的占用空间大小
4 指向函数的指针,用于确定排序的顺序
回调函数
qsort原型中有传入函数指针int (*)(const void*, const void*)
,而这个函数需要用户自行编写,这种通过传入函数指针的方式,在代码内通过该指针来调用函数的方式叫做回调函数
模拟原理
qsort可以对任意同类型的数据进行排序,因为该函数对数据的操作是通过字节操作的,所以需要传入的参数中有数据个数和数据长度,方便数据逐字节操作。
当然,因为是通过字节操作,代码其中充斥了大量的强制类型转换
之所以实现该代码,是为了通过模拟实现qsort来加深对函数指针的理解
实现代码
代码github地址
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <windows.h>
#include <search.h>
#include <stdlib.h>
#include <assert.h>
void my_sort(void* base, size_t count, size_t size, int(*cmp)(const void* elem1, const void* elem2));
void swap(void* data1, void* data2, size_t size);//辅助my_sort函数
int float_cmp(const void* elem1, const void* elem2);
int int_cmp(const void* elem1, const void* elem2);
int str_cmp(const void* elem1, const void* elem2);
int main()
{
int i = 0;
int arr[] = { 9,5,6,7,8,1,3,6,4,3 };
int size = sizeof(arr) / sizeof(arr[0]);
//qsort(arr, size, sizeof(int), int_cmp);
my_sort(arr, size, sizeof(int), int_cmp);//使用和qosrt一样的参数
for (i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
system("pause");
return 0;
}
void my_sort(void* base, size_t count, size_t size, int(*cmp)(const void* elem1, const void* elem2))
{
assert(base);//传入参数要确保base和cmp不为空
assert(cmp);
unsigned int i = 0;
while ((count--) - 1)//冒泡排序,count个参数就排序count-1
{
for (i = 0; i < count; i++)
{
if (cmp((char*)base + size * i, (char*)base + (i + 1) * size))//比较函数,需要用户做自己编写
{
swap((char*)base + size * i, (char*)base + (i + 1) * size, size);//交换函数
}
}
}
}
static void swap(void* data1, void* data2, size_t size)
{
int i = 0;
while(size--)//按字节交换数据
{
char tmp = *(char*)data1;
*(char*)data1 = *(char*)data2;
*(char*)data2 = tmp;
(char*)data1 = (char*)data1 + 1;
(char*)data2 = (char*)data2 + 1;
}
}
int int_cmp(const void* elem1, const void* elem2)//自行编写比较函数
{
return *(int*)elem1 > *(int*)elem2;
}
int float_cmp(const void* elem1, const void* elem2)
{
return *(float*)elem1 > *(float*)elem2;
}
int str_cmp(const void* elem1, const void* elem2)
{
return strcmp((char*)elem1 ,(char*)elem2);
}