C++ 怎么实现二分法 C++ binary_search标准库函数使用【查找】

1次阅读

std::binary_search只返回bool值,不返回下标;需获取下标应使用lower_bound或upper_bound,它们返回迭代器,可转为索引。

C++ 怎么实现二分法 C++ binary_search标准库函数使用【查找】

binary_search 是什么,它能直接返回下标吗

std::binary_search 只返回 truefalse,表示元素是否存在。它**不返回位置**,也不保证是第一个或最后一个匹配项。如果你需要下标(比如想修改、插入或继续处理),不能只靠 binary_search

想查下标?用 lower_bound 或 upper_bound

真正做“二分查找并取位置”的主力是 lower_boundupper_bound

  • lower_bound(first, last, val) 返回第一个 ≥ val 的迭代器
  • upper_bound(first, last, val) 返回第一个 > val 的迭代器
  • 两者都要求容器已升序排列(默认比较),否则行为未定义
  • 若没找到,返回 last —— 一定要检查是否越界再解引用

例如查值为 5 的起始位置:

std::vector v = {1, 3, 5, 5, 5, 7, 9}; auto it = std::lower_bound(v.begin(), v.end(), 5); if (it != v.end() && *it == 5) {     int idx = it - v.begin(); // idx == 2 }

自己写二分循环?注意边界和死循环

手写时最容易错的是 left/right 更新方式和终止条件。常见错误包括:

立即学习C++免费学习笔记(深入)”;

  • 却漏掉 mid 的更新,导致死循环
  • right 初始化为 size(),却忘了 mid 计算可能越界(实际不会,但逻辑易混)
  • 查第一个/最后一个匹配项时,right = mid 还是 right = mid - 1 搞反

安全写法(查第一个匹配):

int left = 0, right = v.size(); while (left < right) {     int mid = left + (right - left) / 2;     if (v[mid] < target) {         left = mid + 1;     } else {         right = mid;     } } // 循环结束时 left == right,检查 v[left] == target

性能和兼容性:vector vs list,排序前提不能忘

binary_searchlower_bound 等函数对随机访问迭代器(如 vectorArray)是 O(log n),对 listforward_list 虽然能编译通过,但实际是 O(n),因为无法 O(1) 跳转到中间——别被接口迷惑。

另一个关键点:它们**不负责排序**。传入未排序的 vector,结果完全不可预测。如果数据动态变化,每次查前都 sort?那总代价是 O(n log n),远不如一次建好有序结构(比如 std::set 或维护插入有序)。

真正在意下标、又频繁增删,vector + 手写二分未必最优;考虑 std::setstd::map,它们底层红黑树天然支持等价查找,但不提供下标——这事没有银弹,得看你的读写比和是否需要索引。

text=ZqhQzanResources