イテレータを返す二分探索を書いているのですが、mid
, dist
などの加減をどう変えてみても正しく判定されないものがいくつか出てきます。
std::distance
の呼び出しを1度で抑えるのが目的なので、できればwhile
内の条件分岐部分を直す方法が知りたいです。
どうすれば良いでしょうか?
#include <functional> #include <iostream> #include <vector> typedef std::vector<int>::const_iterator Iterator; template<class Compare> Iterator BinarySearch(Iterator begin, Iterator end, Compare comp) { auto dist = std::distance(begin, end); auto it = begin; auto not_found = end; while (dist > 0) { auto mid = it; dist /= 2; std::advance(mid, dist); auto comp_result = comp(*mid); if (comp_result == 0) { return mid; } else if (comp_result < 0) { // *midが探索対象より小さい it = ++mid; --dist; } else { // *midが探索対象より大きい end = --mid; --dist; } } return not_found; } int main() { std::vector list1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; std::vector list2{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; std::vector test_numbers{-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; auto bin_search_wrapper = [](std::vector<int> &list, int target) { return BinarySearch(std::begin(list), std::end(list), [target](const int &cur) { if (cur < target) { return -1; } else if (cur == target) { return 0; } return 1; }); }; std::cout << "Test BinarySearch()\n" << "list1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\n"; for (const auto &n : test_numbers) { if (auto it = bin_search_wrapper(list1, n); it != std::end(list1)) { std::cout << n << ": found" << "\n"; } else { std::cout << n << ": not found" << "\n"; } } std::cout << "\nlist2{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}\n"; for (const auto &n : test_numbers) { if (auto it = bin_search_wrapper(list2, n); it != std::end(list2)) { std::cout << n << ": found" << "\n"; } else { std::cout << n << ": not found" << "\n"; } } }
回答2件
あなたの回答
tips
プレビュー