二进制搜索 - 为什么ceil?

时间:2017-04-27 09:31:03

标签: c++ algorithm binary-search

我正在研究二进制搜索算法,我已经多次看到编写如下的算法(这是C ++,但语言在这里并不重要):

    int start = 0;
    int end = vec.size() - 1;       
    do {
        int mid = (lo + hi) / 2;
        if (target < vec[mid])
          start = mid + 1;
        else if (target > vec[mid])
          end = mid - 1;
        else
          // found
    } while (start <= end);

但是我也看到过这样的实现:

    int start = 0;
    int end = vec.size() - 1;       
    do {
        int mid = (int)ceil((lo + hi) / 2.0);
        if (target < vec[mid])
          start = mid + 1;
        else if (target > vec[mid])
          end = mid - 1;
        else
          // found
    } while (start <= end);

两者似乎都有效。是否有正确性或性能原因我应该获取ceil并执行第二种情况浮点运算而不是使用第一个版本?

1 个答案:

答案 0 :(得分:2)

int mid = (lo + hi) / 2时:

当[left,right]之间的数组大小为奇数时,你通过取两个潜在中间元素的左元素决定mid元素,即对于数组[4,5],你的mid将是4。因此,如果没有任何ceil floor,则除法的工作方式与floor非常相似。

(int)ceil((lo + hi) / 2.0);时:

当[left,right]之间的数组大小为奇数时,你通过取两个潜在中间元素的正确元素决定mid元素,即[4,5]你的mid将是5。 / p>

因此,这两个选项都会有效,因为您根据某些有效条件(target < vec[mid]target > vec[mid])放弃/获取某个部分,分区点在这里很重要

另一件事是,在int mid = (lo + hi) / 2等操作期间,如果求和超出整数范围,则在添加lohi时可能会遇到溢出。如此安全就是写mid = lo + (hi - lo) / 2,这将产生相同的输出。

希望它有所帮助!

修改

  

所以两者之所以有效,只是因为我从新的元素中丢弃了mid元素   重启搜索时的搜索范围,对吧?

是。如果你不放弃mid元素,它将落入无限循环,即[4,5],4将始终被选为mid,而对于left = mid这样的调用,它会创造一个无限循环。