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