【发布时间】:2011-04-07 09:10:37
【问题描述】:
如果容器中不存在确切的值,我正在寻找一种 STL 排序,该排序将元素“最接近”返回到目标值。它需要很快,所以基本上我正在寻找一个稍微修改的二进制搜索......我可以写它,但它似乎应该已经存在......
【问题讨论】:
如果容器中不存在确切的值,我正在寻找一种 STL 排序,该排序将元素“最接近”返回到目标值。它需要很快,所以基本上我正在寻找一个稍微修改的二进制搜索......我可以写它,但它似乎应该已经存在......
【问题讨论】:
您是指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 的元素就是您要查找的元素【讨论】:
lower_bound 将返回大于或等于给定值的第一个元素,upper_bound 返回小于或等于给定值的最后一个值。这些方法不关心下一个值是否更接近。
所以您正在寻找与某个值 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 的答案。
【讨论】:
如果容器已经排序(如暗示的那样),您应该能够使用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 和已建议的谓词。
【讨论】:
upper_bound(begin,end,value);
upper_bound 返回end 怎么办?那么该函数是否应该返回end 之前的最后一个元素?
如果您的数据未排序,请使用 std::min_element 和计算距离的比较函子。
【讨论】: