繁体   English   中英

请为我解释这个二进制搜索 function

[英]please explain this binary search function for me

下面是 Apple 的通用二进制搜索代码。 我不擅长位操作等,所以这对我来说真的很难理解。 我在下面的代码中评论了我理解的部分

  1. 什么是基础? 这是包含值的数组吗?

  2. 如果 nremain 是数组中尚未分析的值的数量,为什么我们每次迭代都将其右移 1?

  3. 还请帮助我理解 forloop 的第一行是什么。 所以我的猜测是 p 指向剩余元素的中点,但我没有得到 (nremain >>1) * width 部分。 什么是宽度? 将 nremain 的右移 1 版本与宽度相乘如何将指针设置为中点?

  4. 当 key > p 并且指针需要移动到下一个元素时,sign > 0。 这是如何通过执行 p + width 来实现的? 同样,知道什么是宽度会非常有帮助。

  5. 我得到我们在每次迭代结束时从 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;
}

我会做出一定的假设(基于我会说的知情猜测):

  1. nmemb是数组的成员数
  2. width等于sizeof(array[0])
  3. base指向数组的第一个成员,base == array[0]
  4. 对数组进行排序(从最小值到最大值)

请注意,向右移位基本上是 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。

  1. for循环将nremain初始化为nmemb ,并循环直到nremain != 0 (或发生return )。 在循环结束时,它将nremain除以 2,将结果向下舍入(右移 1)。

  2. p被声明为指向void的指针,该指针设置在nremain (要考虑的数组元素数)乘以width的一半的基本偏移量处。 因此p将指向数组左半部分的末尾。 例如,如果数组中有 7 个元素,则在第一次迭代中p将指向第 4 个元素。 cast (char *) base只是确保添加了正确的字节数,假设width == sizeof(array[0]) ,因为sizeof(char) == 1

  3. compar然后将pkey进行比较,成功时返回p

  4. 如果p < keybase设置为p指向的成员之后的下一个成员,并且从nremain中减去 1 。 这是Eric Postpischil的解释:“对p的先前分配有效地将数组划分为三部分: p指向的元素、之前的元素和之后的元素。之前的元素数量是nremain>>1 ,恰好在p处的数字是1 ,它后面的数字是(nremain-1)>>1例如,如果nremain是 12,则部分有 6、1 和 5 个元素。在该点从nremain中减去 1确保通过nremain >>= 1步骤正确设置它以进行下一次迭代。”

  5. 重申。

  6. 如果我们没有找到值并退出for循环(请注意,当nremain == 1在循环结束时nremain >> 1 == 0 ),返回NULL

也许我的某些假设是错误的,因此您需要通过更改它们来解决代码;)。 希望这可以帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM