C生万物 | 从浅入深理解指针【第四部分】(qsort的使用和模拟实现)

简介: C生万物 | 从浅入深理解指针【第四部分】(qsort的使用和模拟实现)

回调函数是什么?

  • 回调函数就是一个通过函数指针调用的函数
  • 如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

qsort使用举例

  • qsort是一个库函数,用来对数据进行排序,可以排任意类型的数据
  • 我们打开cplusplus网站搜索qsort

这个qsort函数有4个参数:

void qsort(void* base, 
         size_t num, 
         size_t size,
           int (*compar)(const void*, const void*));
  • 第一个参数是指向待排序的第一个元素
  • 第二个参数是待排序的元素个数
  • 第三个参数是待排序的数组元素的大小(单位是字节)
  • 第四个参数是比较两个元素
  • 这里有个void*的指针类型,这个指针类型是通用指针类型,这个指针类型可以接收任意类型数据的地址,就可以理解成指针垃圾桶,谁的地址都可以往里扔~~
  • 是一个无具体类型的指针,所以就不能+1,也不能解引用

我们也介绍完了这个函数,我们来使用一下

写出我们的主函数:

int main()
{
  int arr[] = { 3,2,5,6,8,7,9,1,4 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  qsort(arr, sz, sizeof(arr[0]), cmp_int);
  for (size_t i = 0; i < sz; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}
  • 下面这里就剩下一个比较函数了,怎么写呢?我们再来看一个网站上面的介绍~~
  • 这个函数能够比较e1和e2指向的两个元素,并给出返回值~~

  • 我们也就按照上面的案例来写~~
int cmp_int(const void* e1, const void* e2)
{
  return *(int*)e1 - *(int*)e2;
}
  • 现在我们来看已经完美排序了~~

qsort函数的模拟实现

使用回调函数,模拟实现qsort(采用冒泡的方式)。

  • 今天我们使用冒泡排序,来实现一个对任意类型能够排序的函数
  • 我们先来实现一个整形的冒泡排序,然后再进行改造~~
void bubble_sort(int arr[], int sz)
{
  int i = 0;
  for ( i = 0; i < sz - 1; i++)
  {
    int j = 0;
    for (j = 0; j < sz - 1 - i; j++)
    {
      if (arr[j] > arr[j + 1])
      {
        int tmp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = tmp;
      }
    }
  }
}
int main()
{
  int arr[] = { 3,2,5,6,8,7,9,1,4 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  bubble_sort(arr, sz);
  for (size_t i = 0; i < sz; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}

接下来我们开始改造~~

  1. 改造参数 – 让这个函数能够接受任意类型的数据
  2. 改造比较方法 – 让函数能够在排序时,比较不同类型的数据
  3. 交换的代码也需要修改
  • 我们来看完整代码
void print_arr(int arr[], int sz)
{
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%d ", arr[i]);
  }
}
void Swap(void* p1, void* p2, int size)
{
  int i = 0;
  for (i = 0; i < size; i++)
  {
    char tmp = *((char*)p1 + i);
    *((char*)p1 + i) = *((char*)p2 + i);
    *((char*)p2 + i) = tmp;
  }
}
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 cmp_int(const void* e1,const void* e2)
{
  return *(int*)e1 - *(int*)e2;
}
void test1()
{
  int arr[] = { 3,2,5,6,8,7,9,1,4 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), cmp_int);
  print_arr(arr,sz);
}
int main()
{
  test1();
  return 0;
} 
  • 可以看到,我们对整形的排序也成功了

相关文章
|
7月前
|
搜索推荐 C语言 C++
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现3
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现
|
7月前
|
存储
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现2
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现
|
7月前
|
C语言
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现1
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现
|
2月前
|
C++
指针中的回调函数与qsort的深度理解与模拟
本文详细介绍了回调函数的概念及其在计算器简化中的应用,以及C++标准库函数qsort的原理和使用示例,包括冒泡排序的模拟实现。
22 1
|
2月前
|
算法 搜索推荐 C语言
【C语言篇】深入理解指针4(模拟实现qsort函数)
【C语言篇】深入理解指针4(模拟实现qsort函数)
26 2
|
6月前
|
机器学习/深度学习 搜索推荐 算法
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
|
7月前
|
算法
指针(6)---qsort函数
指针(6)---qsort函数
37 0
|
7月前
|
编译器 C语言
C语言进阶⑪(指针上)(知识点和对应练习)回调函数模拟实现qsort。(下)
C语言进阶⑪(指针上)(知识点和对应练习)回调函数模拟实现qsort。
46 0
C生万物 | 从浅入深理解指针【最后部分】(二)
C生万物 | 从浅入深理解指针【最后部分】(二)
|
7月前
|
存储 C语言
C语言进阶⑪(指针上)(知识点和对应练习)回调函数模拟实现qsort。(中)
C语言进阶⑪(指针上)(知识点和对应练习)回调函数模拟实现qsort。
40 0