库函数的模拟实现(qsort)

一、回调函数

在讲qsort函数之前我们先得熟悉一下回调函数,看到回调函数这个名词有些小伙伴可能觉得有点陌生,其实他就是通过函数指针调用的函数。不太清楚函数指针的朋友可以看看我之前写的博客,链接在下方。http://t.csdnimg.cn/UNrMuicon-default.png?t=N7T8http://深入探寻指针奥秘之"它们"与指针的爱恨情仇

 回调函数:如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用作调用其所指向的函数时,被调用的函数就是回调函数。

#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的网址!

函数总结:

  1. 参数说明:

    • base: 指向要排序的数组的第一个对象的指针,转换为void*类型。
    • num: 数组中的元素数量,使用size_t类型,这是一个无符号整型。
    • size: 数组中每个元素的大小(以字节为单位),也使用size_t类型。
    • compar: 一个比较函数的指针,qsort会反复调用这个函数来比较两个元素。
  2. 比较函数 (compar):

    • 必须遵循特定的原型:int compar(const void*, const void*);
    • 接受两个const void*类型的参数,即指向要比较的两个元素的指针。
    • 必须以稳定且可传递的方式返回以下值之一:
      • 小于0:第一个参数指向的元素排在第二个之前。
      • 等于0:两个元素等价。
      • 大于0:第一个参数指向的元素排在第二个之后。
  3. 元素类型:

    • 由于qsort使用void*作为基础指针类型,它可以对任何类型的数组进行排序,只要提供了合适的比较函数。
  4. 返回值:

    • qsort不返回任何值,它直接修改base指向的数组内容,重新排序其元素。
  5. 使用示例:

    • 对于可以使用常规关系运算符比较的类型,可以编写一个通用的比较函数,如示例中的compareMyType函数。
  6. 类型安全:

    • 由于qsort使用void*指针,调用者需要确保在调用比较函数时正确地将这些指针转换为适当的类型。
  7. 内存分配:

    • 调用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;

}

代码详解:

  1. 比较函数int_cmp:

    int int_cmp(const void* a, const void* b) { return (*(int*)a - *(int*)b); }

    这是一个比较两个整数的函数,它接受两个void类型的指针,将它们转换为int类型指针,然后比较它们指向的整数值。如果a指向的值小于b指向的值,结果为负;如果相等,结果为0;如果a指向的值大于b指向的值,结果为正。

  2. 交换函数_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类型的指针和要交换的大小(以字节为单位)。通过逐字节交换,它实现了两个元素的值交换。

  3. 冒泡排序函数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函数交换它们的位置。

本期内容到此结束啦,如果对你有帮助的话点亮小星星把!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值