在java中为了避免 low+high溢出,可以用无符号右移:正数高位补0,负数高位补1

int mid = (low + high) >>> 1;

如果是在c++中,那么需要先转换为unsigned的再移位

int a=100;
int b;
b=((unsigned int)a)>>1;

或者 int mid = low + ((high - low) / 2);

public static int binarySearch(int[] a, int target) {
int low = 0;
int high = a.length - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
int midVal = a[mid];
if (midVal < target)
low = mid + 1;
else if (midVal > target)
high = mid - 1;
else
return mid;
}
return -1;
}

  

C语言中 bsearch 包含在<stdlib.h>头文件中,此函数可以根据你给的条件实现二分查找,如果找到元素则返回指向该元素的指针,否则返回NULL;对于有多个元素匹配成功的情况,bsearch()未定义返回哪一个。使用 bsearch 函数也要自己定义比较子函数。

函数原型

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 比较两个元素的函数,定义比较规则。需要注意的是,查找数组必须是经过预先排序的,而排序的规则要和比较子函数cmp的规则相同。

因为使用bsearch函数要求数组预先排好序,所以该函数通常和快速排序函数(qsort)一起使用,关于qsort函数,详见《C语言标准库函数 qsort 详解

关于bsearch()的具体应用请见《POJ 2503 Babelfish C语言版

 
void *
bsearch (const void *key, //查找项
const void *base, //元素数组的起始地址
size_t nmemb, //元素的个数
size_t size, //每个元素的长度(大小)
int (*compar) (const void *, const void *)) //比较两个元素的大小的函数
{
size_t l, u, idx;
const void *p;
int comparison; l = 0;
u = nmemb;
while (l < u)
{
idx = (l + u) / 2; //找出中间点的偏移量,注意(l+u)
p = (void *) (((const char *) base) + (idx * size)); //找到中间点
comparison = (*compar) (key, p); //获得中间元素和关键字key之间的额比较值
if (comparison < 0) //key小于中间值,落在左边区间,无需移动元素数组的起始地址
u = idx; //只要修改区间长度
else if (comparison > 0)
l = idx + 1; //修改数组元素的起始位置,构成一个新的数组
else
return (void *) p;
} return NULL;
}

  

void* Bsearch(void* base, int len, int size, const void* key, int (*cmp)(const void* a, const void* b))
{
assert(base != NULL && len >= 0 && size >= 1 && cmp != NULL);
int low = 0;
int high = len - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
char* pmid = (char*)base + mid * size;
if (cmp(pmid, key) < 0) {
low = mid + 1;
} else if (cmp(pmid, key) > 0) {
high = mid - 1;
} else {
return pmid;
} }
return NULL;
}

  

 
 
 
 
 
 
 
 
 
C语言中可以用bsearch()实现二分查找。同qsort()一样,bsearch()也包含在<stdlib.h>库中,且同样要自定义比较子函数。其原型如下:
 

void *bsearch(const void *key, const void *base, size_t nmem, size_t size, int (*comp)(constvoid *, const void *));

key指向所要查找的元素,base指向进行查找的数组,nmem为查找长度,一般为数组长度,size为每个元素所占的字节数,一般用sizeof(...)表示,comp指向比较子函数,它定义比较的规则。需要注意的是,数据必须是经过预先排序的,而排序的规则要和comp所指向比较子函数的规则相同。如果查找成功则返回数组中匹配元素的地址,反之则返回空。对于有多于一个的元素匹配成功的情况,bsearch()未定义返回哪一个。

例:

一、对int类型数组排序

int num[100];

int cmp ( const void *a , const void *b )
{
return *(int *)a - *(int *)b;
} qsort(num,100,sizeof(num[0]),cmp); 二、对char类型数组排序(同int类型) char word[100]; int cmp( const void *a , const void *b )
{
return *(char *)a - *(int *)b;
} qsort(word,100,sizeof(word[0]),cmp); 三、对double类型数组排序 double in[100]; int cmp( const void *a , const void *b )
{
return *(double *)a > *(double *)b ? 1 : -1;
} qsort(in,100,sizeof(in[0]),cmp); 四、对结构体一级排序 struct Sample
{
double data;
int other;
}s[100] //按照data的值从小到大将结构体排序 int cmp( const void *a ,const void *b)
{
return (*(Sample *)a).data > (*(Sample *)b).data ? 1 : -1;
} qsort(s,100,sizeof(s[0]),cmp); 五、对结构体二级排序 struct Sample
{
int x;
int y;
}s[100]; //按照x从小到大排序,当x相等时按照y从大到小排序 int cmp( const void *a , const void *b )
{
struct Sample *c = (Sample *)a;
struct Sample *d = (Sample *)b;
if(c->x != d->x) return c->x - d->x;
else return d->y - c->y;
} qsort(s,100,sizeof(s[0]),cmp); 六、对字符串进行排序 struct Sample
{
int data;
char str[100];
}s[100]; //按照结构体中字符串str的字典顺序排序 int cmp ( const void *a , const void *b )
{
return strcmp( (*(Sample *)a).str , (*(Sample *)b).str );
} qsort(s,100,sizeof(s[0]),cmp); 附加一个完整点的代码,对字符串二维数组排序: #include <stdio.h>
#include <stdlib.h>
#include <string.h> char s[2001][1001]; int cmp(const void *a, const void *b){
return strcmp((char *)a,(char *)b);
} int main(){
int i,n;
scanf("%d",&n);
getchar();
for(i=0;i<n;i++) gets(s[i]);
qsort(s,n,1001*sizeof(char),cmp);
for(i=0;i<n;i++) puts(s[i]);
return 0;
}

  

 
 

#include <stdio.h>
#include <stdlib.h>

#define NUM 8

int compare(const void *p, const void *q)
{
    return (*(int *)p - *(int *)q);
}

int main(int argc, char *argv[])
{
    int array[NUM] = {9, 2, 7, 11, 3, 87, 34, 6};
    int key = 3;
    int *p;

qsort(array, NUM, sizeof(int), compare);
    p = (int *)bsearch(&key, array, NUM, sizeof(int), compare);

(p == NULL) ? puts("not found") : puts("found");

return 0;
}

bsearch的更多相关文章

  1. C 语言中用bsearch()实现查找操作

    C语言中可以用bsearch()实现二分查找.同qsort()一样,bsearch()也包含在库中,且同样要自定义比较子函数.其原型如下: void *bsearch(const void *key, ...

  2. 模板:qsort+bsearch应用

    (1)qsort: 功 能: 使用快速排序例程进行排序 头文件:stdlib.h 用 法: void qsort(void *base,int nelem,int width,int (*fcmp)( ...

  3. 深入理解CPP与C中bsearch函数的用法

    ·使用besearch函数的前提(一些废话) 首先让我们先亮出二分法的定义: https://baike.baidu.com/item/二分法/1364267 以及二分法实现的方法: https:// ...

  4. sort(排序) qsort(快排) bsearch(二分查找)

    sort: 一.对int类型数组排序 int a[100]; int cmp ( int a , int b ) //不必强制转换 { return a < b;//升序排列. } sort ( ...

  5. minix中二分查找bsearch的实现

    在看minix中bsearch实现的源代码之前,先学习一下C 语言中void类型以及void*类型的使用方法与技巧. void的含义: void的字面意思是“无类型”,void *则为“无类型指针”, ...

  6. 数据结构及算法篇bsearch crypt lfind lsearch qsort rand srand

    crypt(将密码或数据编码) 相关函数 getpass 表头文件 #define _XOPEN_SOURCE #include<unistd.h> 定义函数 char * crypt ( ...

  7. qsort()和bsearch()

    qsort void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*)); Sort ...

  8. stdlib.h中自带的两个算法qsort,bsearch

    http://zh.cppreference.com/w/c/algorithm ========== void qsort( void *ptr, size_t count, size_t size ...

  9. C语言标准库 qsort bsearch 源码实现

    C语言是简洁的强大的,当然也有很多坑.C语言也是有点业界良心的,至少它实现了2个最最常用的算法:快速排序和二分查找. 我们知道,对于C语言标准库 qsort和 bsearch: a. 它是“泛型”的, ...

随机推荐

  1. Supervisor – 用于 Unix 系统的进程监控工具

    Supervisor 是一个客户端/服务端模式的系统,使用户能够监视和控制 UNIX 操作系统的进程.Supervisor 为你提供一个地方来启动,停止和监视进程.进程可以单独或成组的形式控制.您还可 ...

  2. BackgroundCheck – 根据图片亮度智能切换元素样式

    BackgroundCheck 是一个轻量的 JavaScript 库,能够根据元素后面的图片的亮度自动切换元素样式.例如在图片幻灯片功能中,根据图片亮度调整导航箭头的颜色,这样让图片和导航的颜色形成 ...

  3. Firefox中一个很好用的host工具--HostAdmin

    支持分组的功能超级好用 host中如下添加 [#] 17 [# COMMENT]#==== 17#192.168.0.17 www.xxx.com#192.168.0.17 1.xxx.com#192 ...

  4. JS 跨域问题常见的五种解决方式

    一.什么是跨域? 要理解跨域问题,就先理解好概念.跨域问题是由于javascript语言安全限制中的同源策略造成的. 简单来说,同源策略是指一段脚本只能读取来自同一来源的窗口和文档的属性,这里的同一来 ...

  5. C#属性封装

    1.属性封装是为了保护与之相对应的字段的,保证字段的读取和赋值是否符合要求 2.属性可以分为:读写,只读,只写 3.允许外部访问的变量一定要申明为属性 4.属性的本质就是两个方法. 5.自动属性 6. ...

  6. ASP.NEt MVC5--创建下拉列表

    Adding Search by Genre If you added the HttpPost version of the Index  method, delete it now. Next, ...

  7. 安装 Oracle P6 EPPM 16 R1 database for 12C A

  8. ADO.NET 增 删 改 查

    ADO.NET:(数据访问技术)就是将C#和MSSQL连接起来的一个纽带 可以通过ADO.NET将内存中的临时数据写入到数据库中 也可以将数据库中的数据提取到内存中供程序调用 ADO.NET所有数据访 ...

  9. Java概述之从源码到运行

    Java体系结构包括以下四个部分: 1. Java语言 2. Java class文件格式(被编译后的java类文件格式) 3. Java API 4. Java虚拟机JVM 它们之间的关系,总结一句 ...

  10. WebApi传参总动员(三)

    上篇介绍了如何从输入流中获取实体对象.本篇介绍以url形式传递参数.简单的参数不再赘述,这里主要实现形如(string name,Woman woman)这样的参数传递. 本篇及后面几章均涉及js调用 ...