vectores una numero mayor matriz imprimir elemento busqueda buscar arreglos arreglo c++ algorithm stl

c++ - una - Manera elegante de encontrar el valor más cercano en un vector desde arriba



imprimir un arreglo en c (5)

Necesito una función que tome un vector (se supone que está ordenado) y un valor, y devuelve el número más cercano que es [edit] mayor que menor o igual que ese número, preferiblemente usando un algoritmo de la STL. He encontrado una solución usando std :: lower_bound (), pero parece desagradable y feo:

struct ClosestCmp { bool operator()(const int & x, const int & y) { return x > y; } }; // vec is assumed to be sorted int closest(const std::vector<int> & vec, int value) { std::vector<int>::const_reverse_iterator cri = std::lower_bound(vec.rbegin(), vec.rend(), value, ClosestCmp()); if (cri != vec.rend()) { return *cri; } return -1; } // ... vec.push_back(1); vec.push_back(2); vec.push_back(4); vec.push_back(5); std::cout << closest(vec, 2) << "/n"; // Should ouput "2" std::cout << closest(vec, 3) << "/n"; // Should ouput "2" std::cout << closest(vec, 4) << "/n"; // Should ouput "4"

¿Alguien puede sugerir una forma más elegante, tal vez usando un algoritmo STL sin necesidad de una función de comparación o un iterador inverso? He buscado en el STL, pero no he podido encontrar una solución mejor que esta.


Algo como esto funcionaría ... Toma el valor más cercano más cercano:

Podría hacerse fácilmente como una plantilla o algo para aquellos que entienden la programación de plantillas. http://ideone.com/ff46ax

#include <iostream> #include <vector> #include <map> #include <stdlib.h> int main() { int comparevalue = 3; typedef std::vector<int> intvec; intvec myvec; myvec.push_back(1); myvec.push_back(2); myvec.push_back(4); myvec.push_back(5); myvec.push_back(6); myvec.push_back(7); typedef std::map<int, int> intmap; intmap mymap; for (intvec::const_iterator itr = myvec.begin(); itr != myvec.end(); ++itr) mymap.insert(std::make_pair(abs(*itr-comparevalue), *itr)); std::cout << "difference:" << mymap.begin()->first << "/n"; std::cout << "value:" << mymap.begin()->second; return 0; }


Para el mayor que sea menor o igual se puede usar esta función.

int closest(std::vector<int> const& vec, int value) { auto const it = std::lower_bound(vec.begin(), vec.end(), value); if (it == vec.begin()) { return -1; } else return *(it - 1); }


Para recordar:

  • std::lower_bound : devuelve el primer valor que no se compara menos
  • std::upper_bound : devuelve el primer valor que se compara estrictamente mayor

Desde su descripción, std::lower_bound ya parece el ajuste perfecto, lo que está mal con:

int closest(std::vector<int> const& vec, int value) { auto const it = std::lower_bound(vec.begin(), vec.end(), value); if (it == vec.end()) { return -1; } return *it; }

Que se utiliza como:

int main() { std::vector<int> vec; vec.push_back(2); vec.push_back(4); std::cout << closest(vec, 2) << "/n"; std::cout << closest(vec, 3) << "/n"; std::cout << closest(vec, 4) << "/n"; }

Salida:

2 4 4


Requiere C ++ 11:

template<typename InputIterator, typename ValueType> InputIterator closest(InputIterator first, InputIterator last, ValueType value) { return std::min_element(first, last, [&](ValueType x, ValueType y) { return std::abs(x - value) < std::abs(y - value); }); }


Solo puede usar std::lower_bound y std::upper_bound con predicados binarios que coinciden con el orden del contenedor. Por lo tanto, no puede ordenar por < y luego usar un predicado binario diferente (diga <= o > ). Así que su "kludge" es en realidad lo correcto a hacer. El vector ordenado a la inversa es el criterio de ordenación que desea utilizar para encontrar el elemento menor o igual al valor. (De lo contrario, si realmente estuviera buscando el valor mayor o igual que, simplemente podría usar std::lower_bound ).