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) int main(int argc, char *argv[]) qsort(array, NUM, sizeof(int), compare); (p == NULL) ? puts("not found") : puts("found"); return 0; |