使用迭代器的二叉搜索,为什么我们使用"(end - begin)/2"?
Binary search using iterators, why do we use "(end - begin)/2"?
我正在研究迭代器,已经花了3天时间弄清楚为什么要使用:
auto mid = text.begin() + (end - beg) / 2;
代码:
int main()
{
vector<int> text{ 10,9,8,7,6,5,4,3,2,1 };
int sought = 3;
// text must be sorted
// beg and end will denote the range we're searching
auto beg = text.begin(), end = text.end();
auto mid = text.begin() + (end - beg) / 2; // original midpoint
// while there are still elements to look at and we haven't yet found sought
while (mid != end && *mid != sought) {
if (sought < *mid) // is the element we want in the first half?
end = mid; // if so, adjust the range to ignore the second half
else // the element we want is in the second half
beg = mid + 1; // start looking with the element just after mid
mid = beg + (end - beg) / 2;// new midpoint
}
system("pause");
}
为什么
auto mid = text.begin() + (end - beg) / 2;
而不是:
auto mid = text.begin() + text.size() / 2;
请帮忙。
这样做是为了避免在将两个非常大的整数相加时可能发生的溢出,其中相加结果可能会大于最大整数限制并产生奇怪的结果。
额外,额外-阅读所有关于它:几乎所有的二进制搜索和合并排序都是损坏的
来自博客:
So what's the best way to fix the bug? Here's one way:
6: int mid = low + ((high - low) / 2);
Probably faster, and arguably as clear is:
6: int mid = (low + high) >>> 1;
In C and C++ (where you don't have the >>> operator), you can do this:
6: mid = ((unsigned int)low + (unsigned int)high)) >> 1;
二进制搜索传统上是这样写的。这种形式的编写有助于程序员理解二进制搜索,因为在标准二进制搜索中只使用开始、结束和中间。
您可以在循环之前使用size()
而不是end-star
,但必须在while循环中使用end-start
,因为end-start
会更改。为了保持一致性,应避免使用size()
。
相关文章:
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- remove(str.begin(), str.end(), );无法正常工作(我正在使用视觉工作室 2012)
- 了解向量中的 .begin 和 .end
- C++ const char with .begin() and .end()
- 为什么 std::find( s.begin(), s.end(), val ) 比集合 s 的 s.find(val) 慢 1000 倍<int>?
- 如何使用vector.begin()和vector.end()遍历矩阵?
- 如何实现 cbegin() 和 cend() 从 begin() 和 end() ?
- C++ - 空的 std::list begin() 和 end() 不相等
- 为什么std::begin()和std::end()适用于固定数组,而不适用于动态数组
- C++代码"x.erase(std::remove(x.begin(), x.end(), ), x.end())"是如何工作的?
- begin(),end()和cbegin(),cend()之间的区别是什么?
- 在模板化数据结构上调用 begin() 或 end()
- 重载 std::begin() 和 std::end() 用于非数组
- 使用 std::set 的 .begin() 和 .end() 函数会产生意想不到的结果
- 使用范围V3视图来实现begin()/end()方法
- 为 C++ 选择 begin() 和 end()
- std::begin() 和 std::end() 不适用于类中的未知长度数组
- 在 std::list 中,std::d istance(it.begin(), std::p rev(it.end()
- 使用迭代器的二叉搜索,为什么我们使用"(end - begin)/2"?