Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

STL "closest" method?

Tags:

c++

search

binary

I'm looking for an STL sort that returns the element "closest" to the target value if the exact value is not present in the container. It needs to be fast, so essentially I'm looking for a slightly modified binary search... I could write it, but it seems like something that should already exist...

like image 840
dicroce Avatar asked Dec 01 '22 10:12

dicroce


2 Answers

Do you mean the lower_bound/upper_bound functions? These perform a binary search and return the closest element above the value you're looking for.

Clarification: The global versions of lower/upper_bound only work if the range is sorted, as they use some kind of binary search internally. (Obviously, the lower/upper_bound methods in std::map always work). You said in your question that you were looking for some kind of binary search, so I'll assume the range is sorted.

Also, Neither lower_bound nor upper_bound returns the closest member. If the value X you're looking for isn't a member of the range, they will both return the first element greater then X. Otherwise, lower_bound will return the first value equal to X, upper_boundwill return the last value equals X.

So to find the closest value, you'd have to

  • call lower_bound
  • if it returns the end of the range, all values are less then X. The last (i.e. the highest) element is the closest one
  • it if returns the beginning of the range, all values are greater then X. The first (i.e. the lowest) element is the closest one
  • if it returns an element in the middle of the range, check that element and the element before - the one that's closer to X is the one you're looking for
like image 78
Niki Avatar answered Dec 05 '22 01:12

Niki


So you're looking for an element which has a minimal distance from some value k?

Use std::transform to transform each x to x-k. The use std::min_element with a comparison function which returns abs(l) < abs(r). Then add k back onto the result.

EDIT: Alternatively, you could just use std::min_element with a comparison function abs(l-k) < abs(r-k), and eliminate the std::transform.

EDIT2: This is good for unsorted containers. For sorted containers, you probably want nikie's answer.

like image 30
Philip Potter Avatar answered Dec 05 '22 02:12

Philip Potter