二分查找是處理有序數據集的經典算法,時間複雜度 O(log n)。本文提供一個通用的 C 語言實現,支援任意資料類型,適合在專案中複用,避免重複造輪子。
void* 泛型指標支援任意類型size 參數計算元素位址piEqual 標記是否精確匹配int bsearch_int(const void *key, const void *base, int nmemb, int size, int *piEqual)
{
size_t l, u, idx;
const void *p, *p2;
int comparison, comparison2;
*piEqual = 0;
if (nmemb < 0) return -1;
if (!nmemb) return 0;
l = 0;
u = nmemb;
while (l < u) {
idx = (l + u) / 2;
p = (void *)(((const char *)base) + (idx * size));
comparison = *(int *)key - *(int *)p;
if (comparison == 0) {
*piEqual = 1;
return idx;
} else if (comparison < 0) {
if (idx == 0) return idx;
p2 = (void *)(((const char *)base) + ((idx - 1) * size));
comparison2 = *(int *)key - *(int *)p2;
if (comparison2 > 0) return idx;
u = idx;
} else { /* comparison > 0 */
l = idx + 1;
}
}
return u;
}
p = (void *)(((const char *)base) + (idx * size));
將 base 轉為 char* 按位元組偏移,再轉回 void*,實現任意類型的位址計算。
idx == 0 時直接回傳,避免 idx - 1 下溢l < u 確保收斂| 情況 | 回傳值 | piEqual |
|---|---|---|
| 找到目標 | 目標索引 | 1 |
| 未找到 | 應插入位置 | 0 |
| 空陣列 | 0 | 0 |
| nmemb < 0 | -1 | 0 |
int arr[] = {10, 20, 30, 40, 50};
int key = 30;
int equal;
int idx = bsearch_int(&key, arr, 5, sizeof(int), &equal);
// idx = 2, equal = 1
int key2 = 25;
int idx2 = bsearch_int(&key2, arr, 5, sizeof(int), &equal);
// idx2 = 2 (插入位置), equal = 0
int (*cmp)(const void*, const void*) 完全泛型化bsearch 標準庫相容介面