哈?会了qsort 我还不知道 bsearch

简介: 正片开始👀qsort👏qsrot 就是C语言库函数中的快速排序函数,对数组,结构体都可以实现快速排序, 他在头文件<stdlib.h>中使用,声明格式为:

正片开始👀

qsort👏

qsrot 就是C语言库函数中的快速排序函数,对数组,结构体都可以实现快速排序, 他在头文件<stdlib.h>中使用,声明格式为:


void qsort(void* base, size_t nums, size_t size, int (*compare)(const void *, const void*))


这么烦人一长串的参数各是什么意思呢,base 是指向要排序的数组的第一个元素的指针。nums是由 base 指向的数组中元素的个数。size 是数组中每个元素的大小,以字节为单位。compare 是用来比较两个元素的函数,这个比较函数需要我们自己补全。


含义

void*代表着任意类型的数组,这个数组也就是我们想用来排序的对象数组;size_t 在系统里面被定义成 int 类型的,所以我们可以把 size_t修饰的数默认为一个整数。


为什么要细化出数组大小和元素大小?这和我排序有毛关系?其实这是为了区分不同类型的数组,int 和 char 类型的数组每个元素所占空间就不一样,自然要区别开。

int main()
{
  int arr[6] = { 1,4,5,8,2,3};
  qsort(arr, 6, sizeof(arr[0]), compare);
}

最后的 compare 函数我是直接将这个元素作为参数传进来,那么问题来了,这个比较函数怎么写?


我们根本不用管那个 *compare 的指针什么鬼,他就相当于告诉你这里在用一个外部函数,我们只要明白整个函数名儿上去就是妥妥的了,这个函数名不一定就叫 compare ,诸君自便。


实现👏

后面的(const void , const void)自然就是这个函数的参数了,两个 void* 实际运用的时候就看成 a ,b,既然是外部函数我们就要自己动手了,我们的最终目的是为了排序,比较函数就应该实现数组元素大小的比较,本质上说就是在比较 a和b 的大小,而a,b是我数组中任意的两两元素。


那首先要做的就是把这个不知道什么类型的 void 指针变成我们给定的,之前代码中给的是整型数组,这里就要对应变成整型指针,这两个指针指向数组中的两个整数,既然要比较,我们就直接做减法看正负即可,把这两个指针转换成真正的整数后就大功告成了:

  int* p = (int*)a;
  int* q = (int*)b;
  int c = *p;
  int d = *q;

成品如下:

#include<stdlib.h>
int compare(const void* a,const void* b)
{
  int* p = (int*)a;
  int* q = (int*)b;
  int c = *p;
  int d = *q;
  return c - d;
}
int main()
{
  int i = 0;
  int arr[6] = { 1,4,5,8,2,3 };
  qsort(arr, 6, sizeof(arr[0]), compare);
  for (i = 0; i < 6; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}

结果如下

image.png

结构体的排序也是同理,如下:

#include<stdlib.h>
typedef struct
{
  int a;
  int b;
  int c;
}arr;
 arr num[4]={
  {1, 2, 3},
  {3, 5, 2},
  {2, 7, 5},
  {4, 3, 6}
};
int compare(const void* a, const void* b)
{
    arr* p = (arr*)a;
  arr* q = (arr*)b;
  int c = p->a;
  int d = q->a;
  return c - d;
}
int main()
{
  int i = 0;
  qsort(num,4 , sizeof(arr), compare);
  for (i = 0; i < 4; i++)
  {
    printf("%d ", num[i].a);
    printf("%d ", num[i].b);
    printf("%d \n", num[i].c);
  }
  return 0;
}

结果就是根据结构体中 a 成员大小来排的:

image.png

格局打开👏

1.上面是实现从小到大排列,要实现从大到小排只需 return d - c 即可。

2.如果是比较浮点数,注意在两个数相差不大时,介于(-1,1),因为现在是整型指针,返回值也是整型,return 回来的就是个 0,造成无意义操作,怎么处理呢?很简单,改成如下即可:

int compare(const void* a,const void* b)
{
  int* p = (int*)a;
  int* q = (int*)b;
  int c = *p;
  int d = *q;
  if(c - d<0)
  {
  return -1;
  }
  else
  {
  return 1;
  }
}

bsearch👏

bsearch (binary search)也是C语言库函数,功能是执行二分查找,声明定义如下

bsearch👏

bsearch (binary search)也是C语言库函数,功能是执行二分查找,声明定义如下


void *bsearch(const void *key, const void *base, size_t nums, size_t size, int (*compar)(const void *, const void *))

1

和 qsort 一样是又臭又长,且随我慢慢看,key 是指向要查找的元素的指针,类型转换为 void*,其他的和 qsort 里的是一样的不再赘述。


强调一下,bsearch()的使用有一个硬性要求,这个数组必须要有顺序性,从大到小或从小到大否则达咩,所以建议和 qsort 配套实验更佳。


这个 key 就是我们的查找目标,void* 代表着一个指针,所以我们在函数里面是不能直接给出的 key 的值,那我们就取他对应的地址就行

  int key = 5;
  bsearch(&key,arr,6,sizeof(int),compare1);

接下来顺水推舟验证一下:

 judge = (int*) bsearch (&key, values, 5, sizeof (int), cmpfunc);
   if( judge != NULL ) 
   {
      printf("find %d is true\n", *judge);
   }
   else 
   {
      printf("%d can not be found\n", *judge);
   }
   return(0);
}

整个代码如下

#include<stdlib.h>
int compare(const void* a, const void* b)
{
  int* p = (int*)a;
  int* q = (int*)b;
  int c = *p;
  int d = *q;
  return c - d;
}
int compare1(const void* key, const void* a)
{
  return (*(int*)key-*(int*)a);
}
int main()
{
  int* judge;
  int arr[6] = { 1,4,5,8,2,3 };
  qsort(arr, 6, sizeof(arr[0]), compare);
  int key = 5;
  judge = (int*)bsearch(&key, arr, 5, sizeof(int), compare1);
  if (judge != NULL)
  {
    printf("find %d is true\n", *judge);
  }
  else
  {
    printf("%d can not be found\n", *judge);
  }
  return(0);
}

image.png


相关文章
|
Ubuntu
百度搜索:蓝易云【Ubuntu删除多余内核教程】
现在,你已经成功地删除了Ubuntu系统中多余的旧内核。请谨慎删除内核,确保保留当前正在使用的稳定内核以及至少一个备用内核,以防止出现意外问题。
647 2
|
SQL 数据库连接 数据库
Qt实用技巧:Qt连接SQL Server数据库(需要配置ODBC)
Qt实用技巧:Qt连接SQL Server数据库(需要配置ODBC)
|
数据采集 Web App开发 监控
高效爬取B站评论:Python爬虫的最佳实践
高效爬取B站评论:Python爬虫的最佳实践
|
机器学习/深度学习 数据采集 数据可视化
TensorFlow,一款由谷歌开发的开源深度学习框架,详细讲解了使用 TensorFlow 构建深度学习模型的步骤
本文介绍了 TensorFlow,一款由谷歌开发的开源深度学习框架,详细讲解了使用 TensorFlow 构建深度学习模型的步骤,包括数据准备、模型定义、损失函数与优化器选择、模型训练与评估、模型保存与部署,并展示了构建全连接神经网络的具体示例。此外,还探讨了 TensorFlow 的高级特性,如自动微分、模型可视化和分布式训练,以及其在未来的发展前景。
1200 5
|
云安全 人工智能 安全
阿里云网络安全体系解析:如何构建数字时代的"安全盾牌"
在数字经济时代,阿里云作为亚太地区最大的云服务提供商,构建了行业领先的网络安全体系。本文解析其网络安全架构的三大核心维度:基础架构安全、核心技术防护和安全管理体系。通过技术创新与体系化防御,阿里云为企业数字化转型提供坚实的安全屏障,确保数据安全与业务连续性。案例显示,某金融客户借助阿里云成功拦截3200万次攻击,降低运维成本40%,响应时间缩短至8分钟。未来,阿里云将继续推进自适应安全架构,助力企业提升核心竞争力。
|
人工智能 IDE 开发工具
C++中的AI编程助手添加
【10月更文挑战第16天】AI 对我们来说就是一个可靠的编程助手,给我们提供了实时的建议和解决方案,无论是快速修复错误、提升代码质量,或者查找关键文档和资源,AI 作为编程助手都能让你事半功倍。
439 1
|
机器学习/深度学习 JSON 数据挖掘
什么是 Python 库?
【8月更文挑战第29天】
1352 5
|
消息中间件 存储 运维
Kafka重要配置参数全面解读(重要)
Kafka重要配置参数全面解读(重要)
1047 2
|
存储 移动开发 关系型数据库
HarmonyOS 鸿蒙面试第一弹
HarmonyOS 鸿蒙面试第一弹
|
Linux 测试技术 API
xenomai内核解析之xenomai初探
本文是关于Xenomai实时操作系统的初探,Xenomai是一个实时性增强的Linux系统,它通过实时内核和用户空间库提供硬实时性能。Xenomai 3主要由实时内核Cobalt、实时驱动模型RTDM、用户空间库libcobalt等组成,支持两种构建实时系统的方式:Cobalt和Mercury。Cobalt在内核空间与标准Linux内核并存,通过I-Pipe处理中断,确保实时任务的执行。Mercury则是通过修改Linux内核实现。
2311 0
xenomai内核解析之xenomai初探