STL“最接近”的方法?

时间:2010-09-02 14:22:38

标签: c++ search binary

我正在寻找一个STL排序,如果容器中没有确切的值,则返回与目标值“最接近”的元素。它需要很快,所以基本上我正在寻找一个略微修改的二进制搜索...我可以写它,但它似乎应该已经存在...

4 个答案:

答案 0 :(得分:9)

您的意思是lower_bound / upper_bound功能吗?这些执行二进制搜索并返回最接近您正在寻找的值的元素。

澄清:lower / upper_bound的全局版本仅在范围排序时才起作用,因为它们在内部使用某种二进制搜索。 (显然,std :: map中的lower / upper_bound方法始终有效)。你在问题中说你正在寻找某种二分搜索,所以我假设范围已经排序。

此外,lower_boundupper_bound都不会返回最近的成员。如果您要查找的值X不是范围的成员,则它们都将返回大于X的第一个元素。否则,lower_bound将返回等于X的第一个值,upper_bound将返回最后一个等于X的值。

所以要找到最接近的值,你必须

  • 致电lower_bound
  • 如果它返回范围的结尾,则所有值都小于X。最后一个(即最高的)元素是最接近的元素
  • 如果返回范围的开头,则所有值都大于X。第一个(即最低的)元素是最接近的元素
  • 如果它返回范围中间的元素,请检查该元素和之前的元素 - 更接近X的元素是您正在寻找的元素

答案 1 :(得分:6)

所以你正在寻找一个与某个值k的距离最小的元素?

使用std::transform将每个x转换为x-k。使用std::min_element和一个返回abs(l) < abs(r)的比较函数。然后将k添加回结果。

编辑:或者,您可以将std::min_element与比较函数abs(l-k) < abs(r-k)一起使用,并取消std::transform

EDIT2:这适用于未分类的容器。对于已分类的容器,您可能需要nikie的答案。

答案 2 :(得分:3)

如果容器已经排序(如暗示的那样),您应该能够直接使用std::upper_bound和项目来确定哪个最接近:

// Untested.
template <class Iter, class T>
Iter closest_value(Iter begin, Iter end, T value)
{
    Iter result = std::upper_bound(begin, end, value);
    if(result != begin)
    {
        Iter lower_result = result;
        --lower_result;
        if(result == end || ((value - *lower_result) < (*result - value)))
        {
            result = lower_result;
        }
    }

    return result;
}

如果容器未排序,请使用min_element和已建议的谓词。

答案 3 :(得分:2)

如果您的数据未排序,请使用std::min_element和计算距离的比较仿函数。