Files

67 lines
2.4 KiB
C
Raw Permalink Normal View History

2026-08-30 22:24:45 +08:00
#ifndef INCLUDED_C_BINARYSEARCH_H
#define INCLUDED_C_BINARYSEARCH_H
#ifndef INCLUDED_C_TYPES_H
#include <c_Types.h>
#endif /*INCLUDED_C_TYPES_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
/**
* @brief 工业级泛型二分查找算法 (类似于标准库 bsearch)
*
* @param key 指向待查找目标对象的指针
* @param base 指向已排序连续数组首元素的指针
* @param num 数组中元素的总个数
* @param size 每个元素所占用的内存字节大小 (sizeof)
* @param cmp 比对回调函数指针 (不能为 NULL)
* @return const void* 找到时返回指向数组中匹配元素的泛型指针;未找到或参数非法时返回 NULL
*/
C_STATIC_FORCE_INLINE
const void* c_BinarySearch(const void* key,
const void* base,
c_size_t num,
c_size_t size,
int (*cmp)(const void* key, const void* elem))
{
// 边界与防御性校验
if (!key || !base || num == 0 || size == 0 || !cmp) {
return NULL;
}
const char* array_base = (const char*)base;
// 🌟【安全加固核心】:采用 c_size_t 无符号左闭右开控制流
c_size_t low = 0;
c_size_t high = num; // 右边界设为 num(开区间),high 永远不需要自减,物理杜绝下溢
while (low < high) { // 🌟 注意:开区间控制条件为 low < high,而不是 <=
// 采用防算术溢出的中间索引计算法
c_size_t mid = low + ((high - low) >> 1);
// 计算当前 mid 元素在扁平内存中的绝对指针位置
const void* mid_elem = (const void*)(array_base + (mid * size));
// 执行用户自定义比对
int cmp_res = cmp(key, mid_elem);
if (cmp_res == 0) {
return mid_elem; // 精确命中,返回该元素的内存首地址
}
else if (cmp_res < 0) {
// 🌟【核心修正】:目标在左侧低位半区,直接收缩右开边界为 mid。
// 彻底干掉了原先“high = mid - 1”引发的 UINT64_MAX 死循环隐患!
high = mid;
}
else {
low = mid + 1; // 目标在右侧高位半区,安全单调向右靠拢
}
}
return NULL; // 未在已排好序的数组中检索到目标
}
#endif /*INCLUDED_C_BINARYSEARCH_H*/