linux源码中的二分法:lib/bsearch.c
2018-01-01 23:28
134 查看
在Linux4.4内核lib目录下的bsearch.c文件给出了内核中的二分查找算法,只有一个函数,也很简单,但是很实用,积累下来,方便以后用的时候直接拿过来使用。此函数用于在已经升序的数组中找到给定目标,关键是利用数组首地址和元素的地址偏移来进行操作,有5个参数:
@key:要查找目标的指针;
@base:升序数组的首地址
@num:升序数组的元素个数
@size:每个元素的大小,即每个元素占多少字节
@cmp:数组元素之间的比较函数指针,这个比较函数需要自己实现,不同的类型使用不同的比较方法。
函数代码如下:
上面的例子中{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}中首先查找21,明显不存在;然后查找7,存在。运行结果如下:
@key:要查找目标的指针;
@base:升序数组的首地址
@num:升序数组的元素个数
@size:每个元素的大小,即每个元素占多少字节
@cmp:数组元素之间的比较函数指针,这个比较函数需要自己实现,不同的类型使用不同的比较方法。
函数代码如下:
#include <linux/export.h> #include <linux/bsearch.h> /* * bsearch - binary search an array of elements * @key: pointer to item being searched for * @base: pointer to first element to search * @num: number of elements * @size: size of each element * @cmp: pointer to comparison function * * This function does a binary search on the given array. The * contents of the array should already be in ascending sorted order * under the provided comparison function. * * Note that the key need not have the same type as the elements in * the array, e.g. key could be a string and the comparison function * could compare the string with the struct's name field. However, if * the key and elements in the array are of the same type, you can use * the same comparison function for both sort() and bsearch(). */ void *bsearch(const void *key, const void *base, size_t num, size_t size, int (*cmp)(const void *key, const void *elt)) { size_t start = 0, end = num; int result; while (start < end) { size_t mid = start + (end - start) / 2; result = cmp(key, base + mid * size);//寻找目标和数组中间值比较 if (result < 0) end = mid;//如果寻找目标小于中间值,则目标在开始和中间之间 else if (result > 0) start = mid + 1;//如果寻找目标大于中间值,则目标在中间和结束之间 else return (void *)base + mid * size;//若相等则找到目标 } return NULL; }写了个小例子来验证,在一个已经排好序的数组中来查找给定目标值,元素为int类型,以此来掌握此函数接口的使用的方法,代码如下
#include <stdlib.h> #include <stdio.h> void *bsearch(const void *key, const void *base, size_t num, size_t size, int (*cmp)(const void *key, const void *elt)){ size_t start = 0, end = num; int result; while (start < end) { size_t mid = start + (end - start) / 2; result = cmp(key, base + mid * size); if (result < 0) end = mid; else if (result > 0) start = mid + 1; else return (void *)base + mid * size; } return NULL; } //compare function int compare(const void *key, const void *elt){ int *a = (int *)key; int *b = (int *)elt; if(*a < *b){ return -1; }else if( *a > *b){ return 1; } return 0; } int main(){ int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; int size = sizeof(arr)/sizeof(arr[0]); int key = 21; int *target = (int *)bsearch((void *)&key, (void *)arr, size, sizeof(int), compare); if(target != NULL){ printf("find target : %d\n", *target); }else{ printf("cannot find the target: %d!\n", key); } int key1 = 7; int *target1 = (int *)bsearch((void *)&key1, (void *)arr, size, sizeof(int), compare); if(target1 != NULL){ printf("find target1 : %d\n", *target1); }else{ printf("cannot find the target1: %d!\n", key1); } return 0; }
上面的例子中{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}中首先查找21,明显不存在;然后查找7,存在。运行结果如下:
相关文章推荐
- Linux网络驱动源码分析(二)
- Linux安装mysql——源码安装(转)
- Linux内核源码分析--内核启动命令行的传递过程(Linux-3.0 ARMv7)
- 【只需3步】Linux php的安装与配置[源码安装]
- linux下源码包安装
- linux 通过源码安装软件
- 3-8·Linux源码包管理、脚本安装包
- linux内核源码目录结构
- Linux Ida and Ird 源码分析
- Linux 源码安装 Python
- linux下用源码编译安装git
- Linux下源码安装lnmp
- Linux驱动修炼之道-SPI驱动框架源码分析(中)
- Davinci DM6446开发攻略——LINUX GPIO驱动源码移植
- linux下如何安装系统源码
- Linux常用命令(远程拷贝、登录、源码阅读器)
- ISC-dhcp server for IPv6 2011-07-26 15:34:31| 分类: linux |字号 订阅 1. 下载源码:http://www.isc.org/softw
- linux 内核源码目录简介
- Linux下C语言实现C/S模式编程(附源码,运行截图)
- Linux操作系统下如何编译安装源码包软件