深入理解CPP与C中bsearch函数的用法
·使用besearch函数的前提(一些废话)
首先让我们先亮出二分法的定义:
https://baike.baidu.com/item/二分法/1364267
以及二分法实现的方法:
https://blog.csdn.net/sufeiboy/article/details/54401257
这些应该是使用二分查找前需要了解的知识,综上我们可以得出:使用besearch前应该先将目标数组进行一定规律的排序,事实上大部分时候我们会使用库中自带的qsort函数进行排序。
·besearch函数的函数原型解析
(资料源于网络)
void *bsearch(const void *key, const void *base, size_t num, size_t size, int (*cmp)(const void *, const void *));
解释一下参数
key: 为要查找的元素的地址
base: 指向进行查找的数组的开始地址
num: 为想要查找的范围,即在多少个数中进行二分查找
size:数组中每个元素的大小,一般用sizeof()表示
cmp:比较两个元素的函数,定义比较规则。这里我们可以类比qsort,首先对于这样一个cmp:
int cmp(const void *p1,const void *p2);
其中p1始终指向的是key的地址,而p2指向的是besearch所查找的数组里的传递过来的元素
其次我们知道qsort对于cmp函数的比较返回值的处理是当返回值为正则交换两个元素,而对于bsearch则为当返回值为0则认为查找到了目标元素。当返回值为正数则besearch会向后进行二分查找,返回值为负数将会向前进行二分查找。 简单的记忆方法便是:升序数组返回p1-p2,降序数组返回p2-p1(这里建议看完使用实例后再看)
关于besearch的返回值: besearch在找到元素后将返回数组中满足cmp条件的这个数的地址,但是这个地址是void *类型的,如果我们不加以类型转换就无法使用。而如果没有找到对应元素则会返回NULL指针,我们可以通过判断返回值的类型得到元素是否在数组中存在。
关于besearch的陷阱: 当数组中存在多个匹配元素时,besearch不能保证返回的指针一定指向某一个特定的元素,此时besearch只能用于证明数组内是否含有特定元素
·bserach的使用实例
#include <stdio.h>
#include <stdlib.h> int cmp(const void *p1,const void *p2)
{
int a=*(int *)p1,b=*(int *)p2;//为了清楚说明进行临时转化保存
return a-b;//仅当a=b时返回0,说明查找到了
}
int main(int argc, char const *argv[])
{
int arry[100];
for(int i=1;i<=100;i++) arry[i-1]=i;
int *ans;//用于接受查找的结果
int key;
scanf("%d",&key);
ans=(int *)bsearch(&key,arry,100,sizeof(int),cmp);//记得对结果进行转换
if (ans!=NULL)
printf("The key:%d exists.The pointer is %X.",key,ans);
else
printf("The key doesn't exists\n");
return 0;
}
四次运行实例:
输入:
13
输出:
The key:13 exists.The pointer is 61FD74.
输入:
60
输出:
The key:60 exists.The pointer is 61FD9C.
输入:
0
输出:
The key doesn't exists
输入:
101
输出
The key doesn't exists
·bserach的使用实例
我们知道,上述的数组是一个升序数组,那么考虑一下情况,如果arry是一个 100 99 98…… 2 1的降序数组此时我们该如何编写cmp函数
其实很简单,根据cmp返回值对besearch的影响,我只需把return语句重写
原本:
int cmp(const void *p1,const void *p2)
{
int a=*(int *)p1,b=*(int *)p2;
return a-b;
}
现在
int cmp(const void *p1,const void *p2)
{
int a=*(int *)p1,b=*(int *)p2;
return b-a;
}
是不是很像qsort的处理方式呢
更进一步的,如果我们要寻找这样一个元素它恰好是key的三倍,那么我们可以这么写:
int cmp(const void *p1,const void *p2)
{
int a=*(int *)p1,b=*(int *)p2;
return 3*a-b;//这里默认arry进行升序排列
}
至此,关于besearch的基本部分便已陈述完毕,实际上我们可以通过besearch进行更复杂的查找,正如网上很多的关于qsort对结构体进行一级甚至多级排序,besearch也同样可以。
本文在此结束,但读者可以自行去探索。
深入理解CPP与C中bsearch函数的用法的更多相关文章
- Oracle 中 CONTAINS 函数的用法
Oracle 中 CONTAINS 函数的用法 1. 查询住址在北京的学生 SELECT student_id,student_name FROM students WHERE CONTAINS( a ...
- matlab中patch函数的用法
http://blog.sina.com.cn/s/blog_707b64550100z1nz.html matlab中patch函数的用法——emily (2011-11-18 17:20:33) ...
- mysql中INSTR函数的用法
mysql中INSTR函数的用法 INSTR(字段名, 字符串) 这个函数返回字符串在某一个字段的内容中的位置, 没有找到字符串返回0,否则返回位置(从1开始) SELECT * FROM tblTo ...
- (转)解析PHP中ob_start()函数的用法
本篇文章是对PHP中ob_start()函数的用法进行了详细的分析介绍,需要的朋友参考下 ob_start()函数用于打开缓冲区,比如header()函数之前如果就有输出,包括回车/空格/换行 ...
- Delphi中 StrToIntDef函数的用法
Delphi中 StrToIntDef函数的用法:比如我要判断一个文本框里输入的字符串能不能转换为integer类型,如果能,则返回转换后的整型数据,如果不能,则返回整数0,那么我就可以用strtoi ...
- Python中int()函数的用法浅析
int()是Python的一个内部函数 Python系统帮助里面是这么说的 >>> help(int) Help on class int in module __builti ...
- matlab中repmat函数的用法(堆叠矩阵)
matlab中repmat函数的用法 B = repmat(A,m,n) B = repmat(A,[m n]) B = repmat(A,[m n p...]) 这是一个处理大矩阵且内容有重复时使用 ...
- Matlab中imfilter()函数的用法
Matlab中imfilter()函数的用法 功能:对任意类型数组或多维图像进行滤波.用法:B = imfilter(A,H) B = imfilter(A,H,option1,option2,... ...
- Oracle trunc()函数,decode()函数,substr函数,GREATEST函数,java中substring函数的用法
--Oracle trunc()函数的用法/**************日期********************/1.select trunc(sysdate) from dual --2013- ...
随机推荐
- 学习string,stringBuffer时遇到的问题
今天学习string和stringBuffer.了解了两者的区别,然后去看java api都有啥方法.stringBuffer类有indexOf方法,于是写了下面的代码 String str = &q ...
- 面试经验合集-Web前端<一>
面试一:MF时间:2019-1-2 试题一 // [mf: stringify-query-string] // 类型: x z // 时长: 15 分钟 // 姓名: // 日期: // 实现下面的 ...
- 第4章学习小结_串(BF&KMP算法)、数组(三元组)
这一章学习之后,我想对串这个部分写一下我的总结体会. 串也有顺序和链式两种存储结构,但大多采用顺序存储结构比较方便.字符串定义可以用字符数组比如:char c[10];也可以用C++中定义一个字符串s ...
- 第31月第19天 NV12
1. //设置CIContext,并从CIImage -> CGImage -> UIImage CIContext *context = [CIContext contextWithOp ...
- CPU或以太网模块重启DHCP请求
最近,带了一个实习生,一天: 他:师傅,PLC如何首次分配IP地址啊? 我:不是教过你了吗? 他:我怎么用BOOTP软件,半天没有反应啊? 我:..... 原来,他做实验的CPU已经被分配IP地址了, ...
- day06 字典、元组、set的方法及常用操作
今日内容: 1.深浅拷贝 2.元组 3.字典 4.set 1.深浅拷贝 # 1.值拷贝 # 采用赋值的方法进行 # 只会将堆区容器变量与栈区的绑定关系进行复制 # 2.浅拷贝 # 会将堆区与栈区的绑定 ...
- Option path is not valid. Please refer to the README.
使用pomelo创建的项目并且安装依赖项目之后启动项目如出现如下错误提示 [2018-12-18 11:23:16.161] [ERROR] console - Option path is not ...
- Linux 用户组
文件权限 r w x 文件时的权限介绍 r 可读 可以使用 cat.less等命令 w 可写 可以编辑,删除此文件 x 可执行 可以命令行模式下提交给内核运行此命令 当时目录时 r 可以使用ls列出 ...
- CentOS下MySQL安装失败,报socket '/tmp/mysql.sock错误解决方法
1.在centos里安装mysql数据库后,登录时提示‘/tmp/mysql.sock’ 第一种解决办法:采用ln链接方式进行处理 ln -s /var/lib/mysql/mysql.sock /t ...
- USACO15DEC最大流MaxFlow
传送门 这是个假的最大流,其实是一个用树剖+线段树就能解决的事情 题目中的道路会对路径上的造成压力,最后询问最大的压力 其实就等价于对每条路径上的点加上 1 的权值,并且最后询问整个树中的最大值 然后 ...