bsearch

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;
}

时间: 2024-10-28 16:05:48

bsearch的相关文章

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

C语言中可以用bsearch()实现二分查找.同qsort()一样,bsearch()也包含在库中,且同样要自定义比较子函数.其原型如下: void *bsearch(const void *key, const void *base, size_t nmem, size_t size, int (*comp)(const void *, const void *)); 头文件:#include<stdlib.h> key指向所要查找的元素,base指向进行查找的数组,nmem为查找长度,一般

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

crypt(将密码或数据编码) 相关函数 getpass 表头文件 #define _XOPEN_SOURCE #include<unistd.h> 定义函数 char * crypt (const char *key,const char * salt); 函数说明 crypt()将使用Data Encryption Standard(DES)演算法将参数key所指的字符串加以编码,key字符串长度仅取前8个字符,超过此长度的字符没有意义.参数salt为两个字 符组成的字符串,由a-z.A-

使用qsort()和bsearch()函数对值和字符串进行排序和查找

#include <stdio.h> #include <stdlib.h> #define MAX 20 int intcmp(const void *v1, const void *v2); int main(void){   int arr[MAX], count, key, *ptr;      //提示用户输入一些整数    printf("Enter %d integer values; press Enter each.\n", MAX);   f

bsearch函数二分法

在初学写程序时,特别是刚开始接触数据结构时,基本都是在查找: 各种排序,其实都是在为查找做准备. ============================= 今天我们来看看关于c语言中自带的一个二分法搜索函数bsearch 通过这个函数可以简单的认识到二分法搜索的一些内在的原理,以及发散一点其他搜索方法的东西. ============================= 首先,介绍这个函数 函数原型: void *bsearch(const void *key, const void *base

排序,查找,qsort和bsearch的简单总结,scanf字符串截取

有一些时候,一些方便用户做的设计,往往会降低产品本身的安全性. 安全性与易用性,是一道产品设计者需要仔细思考的题. ========================================================================================================== 好了,切入正题.最近在练题,或者说刷题,发现自己不知道的东西还真不少,得好好补补啦~ 首先就是c语言的两个,也是唯一的两个与排序搜索相关的函数,记得之前自己还很仔细的去背

bsearch的使用

懒得写二分查找,结果发现stdlib里自带了二分查找. C 库函数 void *bsearch(const void *key, const void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *)) 对 nitems 对象的数组执行二分查找,base 指向进行查找的数组,key 指向要查找的元素,size 指定数组中每个元素的大小.数组的内容应根据 compar 所对应的比较函数升序排序.

bsearch的溢出问题

在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) { in

二分查找

递归版(在区间[x, y)中找v的位置) 1 //递归版二分查找 2 int bsearch(int * A, int x, int y, int v) 3 { 4 5 if(v<a[x] || v>a[y-1]) return -1; 6 int m = x + (y-x)/2; //此处能不能用int m = (x+y)/2,需要仔细考虑(暂时想不到原因) 7 if(A[m]==v) return m; 8 else if(A[m]>v) return bsearch(A, x, m

BZOJ_1014_[JSOI2008]_火星人prefix_(Splay+LCP_Hash+二分)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1014 给出一个字符串,有修改,插入,以及询问LCP(i,j)的操作. 分析 LCP在白书上面有介绍,\(LCP(i,j)\)表示以第\(i\)位和以第\(j\)位开头的后缀的最长公共前缀. 先考虑没有插入和修改操作的问题.我们可以用基于Hash的LCP算法. 我们给每一个后缀一个Hash值.其中以第\(i\)为开头的后缀的Hash值为\(H[i]=H[i+1]x+s[i]\). 其中\(x\