[英]please explain this binary search function for me
下面是 Apple 的通用二进制搜索代码。 我不擅长位操作等,所以这对我来说真的很难理解。 我在下面的代码中评论了我理解的部分
什么是基础? 这是包含值的数组吗?
如果 nremain 是数组中尚未分析的值的数量,为什么我们每次迭代都将其右移 1?
还请帮助我理解 forloop 的第一行是什么。 所以我的猜测是 p 指向剩余元素的中点,但我没有得到 (nremain >>1) * width 部分。 什么是宽度? 将 nremain 的右移 1 版本与宽度相乘如何将指针设置为中点?
当 key > p 并且指针需要移动到下一个元素时,sign > 0。 这是如何通过执行 p + width 来实现的? 同样,知道什么是宽度会非常有帮助。
我得到我们在每次迭代结束时从 nremain 中减去 1 以表示已经分析了一个元素,但是在这种情况下每次迭代 nremain>>=1 有什么意义?
提前致谢。 我期待收到任何人的回音。
void *apple_bsearch(const void *key, const void *base, size_t nmemb,
size_t width, int (*compar)(const void *, const void *)) {
for (size_t nremain = nmemb; nremain != 0; nremain >>= 1) {
void *p = (char *)base + (nremain >> 1) * width; // I don't get this
// this is comparing key & where currently p is pointing
int sign = compar(key, p);
if (sign == 0) { // if p and key are equal, sign is 0
return p;
}
if (sign > 0) { // when key > p, move right
base = (char *)p + width;
nremain--;
}
}
return NULL;
}
我会做出一定的假设(基于我会说的知情猜测):
nmemb
是数组的成员数width
等于sizeof(array[0])
base
指向数组的第一个成员,即base == array[0]
请注意,向右移位基本上是 integer 除法(它丢弃余数,例如3 >> 1 == 1
)。
function 采用以下 arguments:
key
,指向 const void 的指针base
, 指向 const void 的指针nmemb
, size_t 变量width
, size_t 变量compar
,(一个指针)指向一个 function 和两个 arguments (2x 指向const void
的指针)返回一个int
使用指向void
的指针这一事实允许 function 不知道数组元素的大小(因此是通用的)。
现在让我们逐行说明 go。
for
循环将nremain
初始化为nmemb
,并循环直到nremain != 0
(或发生return
)。 在循环结束时,它将nremain
除以 2,将结果向下舍入(右移 1)。
p
被声明为指向void
的指针,该指针设置在nremain
(要考虑的数组元素数)乘以width
的一半的基本偏移量处。 因此p
将指向数组左半部分的末尾。 例如,如果数组中有 7 个元素,则在第一次迭代中p
将指向第 4 个元素。 cast (char *) base
只是确保添加了正确的字节数,假设width == sizeof(array[0])
,因为sizeof(char) == 1
。
compar
然后将p
与key
进行比较,成功时返回p
。
如果p < key
则base
设置为p
指向的成员之后的下一个成员,并且从nremain
中减去 1 。 这是Eric Postpischil的解释:“对p
的先前分配有效地将数组划分为三部分: p
指向的元素、之前的元素和之后的元素。之前的元素数量是nremain>>1
,恰好在p
处的数字是1
,它后面的数字是(nremain-1)>>1
。例如,如果nremain
是 12,则部分有 6、1 和 5 个元素。在该点从nremain
中减去 1确保通过nremain >>= 1
步骤正确设置它以进行下一次迭代。”
重申。
如果我们没有找到值并退出for
循环(请注意,当nremain == 1
在循环结束时nremain >> 1 == 0
),返回NULL
。
也许我的某些假设是错误的,因此您需要通过更改它们来解决代码;)。 希望这可以帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.