You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通用二进制搜索函数实现问询:支持多类型数组

通用二分查找函数实现(支持多数据类型)

你原来的思路存在两个核心问题:一是void*指针无法直接获取元素大小(sizeof(array[0])属于非法操作),二是仅靠元素大小无法区分有符号/无符号类型的比较逻辑。下面是最优实现方案,通过传入元素大小、数组长度和自定义比较函数来实现通用型二分查找:

核心思路

  1. 用void*接收任意类型的数组指针,打破单一类型限制;
  2. 显式传入元素字节大小,用来计算数组中每个元素的内存偏移;
  3. 传入自定义比较函数,处理不同类型的大小比较逻辑(比如有符号和无符号的差异);
  4. 补充数组长度参数,二分查找必须依赖边界信息才能正确执行。

完整代码实现

通用二分查找函数

#include <stdint.h>
#include <stddef.h>

// 比较函数类型定义:返回值 <0 表示a < b,=0表示a==b,>0表示a>b
typedef int (*CompareFunc)(const void* a, const void* b);

// 查找成功返回目标元素的索引,失败返回SIZE_MAX
size_t binary_search(const void* array, size_t length, size_t elem_size, const void* target, CompareFunc cmp) {
    size_t left = 0;
    size_t right = length - 1;

    while (left <= right) {
        // 计算中间元素的内存地址:用char*做偏移,确保字节级精确计算
        size_t mid_idx = left + (right - left) / 2;
        const void* mid_elem = (const char*)array + mid_idx * elem_size;
        int cmp_result = cmp(mid_elem, target);

        if (cmp_result == 0) {
            return mid_idx; // 返回索引
        } else if (cmp_result < 0) {
            left = mid_idx + 1;
        } else {
            right = mid_idx - 1;
        }
    }

    return SIZE_MAX; // 未找到目标元素
}

针对不同类型的比较函数

// uint8_t类型比较
int cmp_uint8(const void* a, const void* b) {
    const uint8_t* val_a = (const uint8_t*)a;
    const uint8_t* val_b = (const uint8_t*)b;
    return (*val_a > *val_b) - (*val_a < *val_b);
}

// int8_t类型比较
int cmp_int8(const void* a, const void* b) {
    const int8_t* val_a = (const int8_t*)a;
    const int8_t* val_b = (const int8_t*)b;
    return (*val_a > *val_b) - (*val_a < *val_b);
}

// uint16_t类型比较
int cmp_uint16(const void* a, const void* b) {
    const uint16_t* val_a = (const uint16_t*)a;
    const uint16_t* val_b = (const uint16_t*)b;
    return (*val_a > *val_b) - (*val_a < *val_b);
}

调用示例

#include <stdio.h>

int main() {
    // uint8_t数组查找
    uint8_t u8_arr[] = {2, 4, 6, 8, 10};
    size_t u8_len = sizeof(u8_arr) / sizeof(u8_arr[0]);
    uint8_t u8_target = 6;
    size_t u8_idx = binary_search(u8_arr, u8_len, sizeof(uint8_t), &u8_target, cmp_uint8);
    if (u8_idx != SIZE_MAX) {
        printf("uint8_t target found at index: %zu\n", u8_idx);
    } else {
        printf("uint8_t target not found\n");
    }

    // int8_t数组查找
    int8_t s8_arr[] = {-10, -5, 0, 5, 10};
    size_t s8_len = sizeof(s8_arr) / sizeof(s8_arr[0]);
    int8_t s8_target = -5;
    size_t s8_idx = binary_search(s8_arr, s8_len, sizeof(int8_t), &s8_target, cmp_int8);
    if (s8_idx != SIZE_MAX) {
        printf("int8_t target found at index: %zu\n", s8_idx);
    } else {
        printf("int8_t target not found\n");
    }

    return 0;
}

关键细节说明

  • 用char*计算偏移:char类型的大小固定为1字节,转换为char*后进行指针加减操作,可以精确计算任意类型元素的内存地址;
  • 比较函数的必要性:即使元素字节大小相同(比如int8_t和uint8_t都是1字节),它们的比较逻辑完全不同,必须通过自定义比较函数区分;
  • 返回值选择:用size_t作为索引类型更符合C语言的规范,SIZE_MAX表示未找到,避免了符号类型转换的潜在问题。

内容的提问来源于stack exchange,提问作者nerd_god

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 01:57:42