You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中无需手写二分查找实现函数结果upper_bound的兼容方案

解决方案

方案1:基于自定义整数迭代器+原生std::upper_bound(无需第三方库)

既然你已经实现了随机访问的整数迭代器MyIntIt,完全可以跳过视图转换,直接把转换逻辑嵌入std::upper_bound的自定义比较器中,这样既不需要C++20 ranges,也能保证二分查找的O(log n)效率。

实现代码如下:

template <class ArgT,
          class ResultT,
          class TransformFunc,
          class Compare = std::less<ResultT>>
ArgT result_upper_bound(ResultT searched, ArgT begin, ArgT end, TransformFunc tf, Compare comp = Compare{}) {
    // 用自定义整数迭代器包装范围边界
    const auto first = MyIntIt<ArgT>(begin);
    const auto last = MyIntIt<ArgT>(end);

    // 调用std::upper_bound,在比较器中完成参数到结果的转换
    auto it = std::upper_bound(first, last, searched,
        [&tf, &comp](const ResultT& target, const ArgT& arg) {
            // 对应upper_bound的逻辑:返回target < tf(arg)(默认comp),即tf(arg) > target
            return comp(target, tf(arg));
        });

    // 解引用迭代器得到最终的参数值
    return *it;
}

这个方案的核心是利用std::upper_bound允许自定义比较器的特性,把原本需要视图做的转换逻辑放到比较步骤中,避免了对C++20 ranges的依赖,同时因为MyIntIt是随机访问迭代器,std::upper_bound会以最优的二分查找效率运行。

方案2:使用Boost.Counting Range(若Boost版本支持随机访问转换迭代器)

如果你的Boost版本足够新(Boost 1.70+),boost::transform_iterator在底层迭代器是随机访问类型时,会自动继承随机访问迭代器的特性,此时可以结合boost::counting_range来实现:

#include <boost/range/counting_range.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/algorithm/range.hpp>

template <class ArgT,
          class ResultT,
          class TransformFunc,
          class Compare = std::less<ResultT>>
ArgT result_upper_bound(ResultT searched, ArgT begin, ArgT end, TransformFunc tf, Compare comp = Compare{}) {
    auto args_range = boost::counting_range(begin, end);
    auto transformed = args_range | boost::adaptors::transformed(tf);
    auto it = boost::algorithm::upper_bound(transformed, searched, comp);
    // 转换回原始参数值:迭代器距离起始的偏移量 + begin
    return begin + std::distance(args_range.begin(), it.base());
}

注意这里需要用it.base()获取转换迭代器的底层整数迭代器,再计算偏移得到原始参数值。如果你的Boost版本确实不支持随机访问的转换迭代器,这个方案会退化为线性查找,此时建议优先选方案1。

方案3:使用Abseil库的数值范围与转换视图

如果你可以引入Abseil库,absl::numeric_range提供了原生的整数随机访问范围,absl::MakeTransformView生成的视图同样保持随机访问特性,配合absl::upper_bound即可高效完成查找:

#include <absl/numeric/numeric_range.h>
#include <absl/algorithm/algorithm.h>
#include <absl/ranges/transform_view.h>

template <class ArgT,
          class ResultT,
          class TransformFunc,
          class Compare = std::less<ResultT>>
ArgT result_upper_bound(ResultT searched, ArgT begin, ArgT end, TransformFunc tf, Compare comp = Compare{}) {
    auto args_range = absl::numeric_range<ArgT>(begin, end);
    auto transformed = absl::MakeTransformView(args_range, tf);
    auto it = absl::upper_bound(transformed, searched, comp);
    return args_range.begin() + std::distance(transformed.begin(), it);
}

内容的提问来源于stack exchange,提问作者Георгий Гуминов

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 12:05:30