我正在寻找一个STL排序,如果容器中没有确切的值,则返回与目标值“最接近”的元素。它需要很快,所以基本上我正在寻找一个略微修改的二进制搜索...我可以写它,但它似乎应该已经存在...
答案 0 :(得分:9)
您的意思是lower_bound
/ upper_bound
功能吗?这些执行二进制搜索并返回最接近您正在寻找的值的元素。
澄清:lower / upper_bound的全局版本仅在范围排序时才起作用,因为它们在内部使用某种二进制搜索。 (显然,std :: map中的lower / upper_bound方法始终有效)。你在问题中说你正在寻找某种二分搜索,所以我假设范围已经排序。
此外,lower_bound
和upper_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和计算距离的比较仿函数。