Двоичный поиск с использованием итераторов, почему мы используем "(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;
Пожалуйста, помогите.
Ответы
Ответ 1
Это делается для того, чтобы избежать переполнения, которое может произойти при добавлении двух очень больших целых чисел, где результат сложения может стать больше максимального предел максимального значения и дать странные результаты.
Extra, Extra - Читать все об этом: почти все бинарные поиски и слияния не найдены
Из блога:
So what the best way to fix the bug? Here 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;
Ответ 2
Бинарный поиск традиционно написан так. Эта форма написания помогает кодировщикам понимать двоичный поиск, поскольку в стандартном двоичном поиске используется только начало, конец, середина.
Вы можете использовать size()
, а не end-star
перед циклом, но вы должны использовать end-start
в цикле while, так как end-start
изменится. Вы должны избегать использования size()
для согласованности.