筑基_C_5_对数组的二分查找

本文详细介绍了如何逐步开发一个泛型二分查找函数bsearch,首先实现了针对整型数组的查找,然后克服负数和指针数组的挑战,通过cmpFn回调函数提供通用比较。通过实例演示了对指针数组的搜索,展示了函数的实用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 泛型函数bsearch()的编写过程

1.1 先实现对整型数组的查找

int8_t BinarySearch(int key, int *arr, uint8_t arrLen)
{
    uint8_t low = 0;
    uint8_t high = arrLen-1;
    uint8_t middle;
    // In ascending order
    while(low <= high) {
        middle = (low + high)>>1;
        if(arr[middle] == key) {
            return middle;
        } else if (arr[middle] > key) {
            high = middle - 1;
        } else {
            low = middle + 1;
        }
    }
    return -1;
}

1.2 尝试使用泛型

/**
 * 问题1:遇到负数使用 memcmp 就完蛋了!!!
 * 问题2:无法支持指针数组
 **/
void *bsearch(void *key, void *arr, 
			uint8_t arrLen, uint8_t elemSize)
{
    uint8_t low = 0;
    uint8_t high = arrLen - 1;
    uint8_t middle;
    void *elemAddr;
	// In ascending order
    while(low <= high) {
        middle = (low + high) >> 1;
        elemAddr = (char *)arr + middle * elemSize;
        if(0 == memcmp(key, elemAddr, elemSize)) {
            return elemAddr;
        } else if(memcmp(key, elemAddr, elemSize) > 0 ) {
            low = middle + 1;
        } else {
            high = middle - 1;
        }
    }
    
    return NULL;
}

1.3 增加对负数和指针数组的支持

void *bsearch(void *key, void *arr, 
			uint8_t arrLen, uint8_t elemSize, 
			int cmpFn(void*, void*))
{
    uint8_t low = 0;
    uint8_t high = arrLen - 1;
    uint8_t middle;
    void *elemAddr;
    int result;
	// In ascending order
    while(low <= high) {
        middle = (low + high) >> 1;
        elemAddr = (char *)arr + middle * elemSize;

        result = cmpFn(key, elemAddr);
        if(0 == result) {
            return elemAddr;
        } else if(result > 0 ) {
            low = middle + 1;
        } else {
            high = middle - 1;
        }
    }
    
    return NULL;
}
int bIntCmp(void *elem1, void *elem2)
{
    int *ip1 = (int *)elem1;
    int *ip2 = (int *)elem2;
    return *ip1 - *ip2;
}

int bStrCmp(void *elem1, void *elem2)
{
    char *cp1 = *(char **)elem1;
    char *cp2 = *(char **)elem2;
    return strcmp(cp1, cp2);
}

2 测试

2.1 对指针数组的二分查找

int arr[] = {-100, -25, -1, 0, 1, 5, 6, 10, 11, 12, 15};
char *str[] = { // ordered list, ascending order
    "ab",
    "abc",
    "abcd",
    "abcde"
};

int main (int argc, char *argv[])
{
    char *strKey = "abc";
    void *get;

    printf("there are %d elems in array\r\n", sizeof(str)/sizeof(char *));
    get = bsearch( &strKey, &str, 
    			sizeof(str)/sizeof(char *), sizeof(char *), 
    			bStrCmp);
    if(NULL != get) {
        printf( "taget %s was founded in position %d\r\n", strKey,  (char **)get - str);
    } else {
        printf("Not founded\r\n");
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值