sináptico
estoy tratando de usar std::min_element
y std::max_element
para devolver los elementos mínimo y máximo en un vector de dobles. A mi compilador no le gusta cómo intento usarlos actualmente y no entiendo el mensaje de error. Por supuesto, podría escribir mi propio procedimiento para encontrar el mínimo y el máximo, pero me gustaría entender cómo usar las funciones.
#include <vector>
#include <algorithm>
using namespace std;
int main(int argc, char** argv) {
double cLower, cUpper;
vector<double> C;
// Code to insert values in C is not shown here
cLower = min_element(C.begin(), C.end());
cUpper = max_element(C.begin(), C.end());
return 0;
}
Aquí está el error del compilador:
../MIXD.cpp:84: error: cannot convert '__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >' to 'double' in assignment
../MIXD.cpp:85: error: cannot convert '__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >' to 'double' in assignment
¿Qué estoy haciendo mal?
min_element
y max_element
devuelve iteradores, no valores. Así que tú necesitas *min_element...
y *max_element...
.
-
Un iterador es un puntero en el sentido de que apunta a cosas. Pero puede o no ser un puntero ordinario. Por ejemplo, si un iterador se refiere a un objeto en una lista, incrementarlo hace que apunte al siguiente objeto en la lista. Incrementar un puntero ordinario solo hace eso para colecciones como un vector que garantiza almacenar su contenido en direcciones de memoria de secuencia.
–David Schwartz
15 de abril de 2012 a las 1:51
-
en caso de que el vector esté vacío
*max_element
genera error. ¿Hay alguna solución para manejar este problema? En este momento compruebo si el vector está vacío o no y luego uso*max_element
– Moj
6 de diciembre de 2013 a las 15:22
-
Creo que esa es la mejor solución. De todos modos, debe manejar el caso de manera especial, porque no hay un valor razonable que pueda devolverse.
–David Schwartz
6 de diciembre de 2013 a las 18:09
-
@Moj: puedes verificar el iterador contra
C.end()
.– intelfx
10/06/2014 a las 15:50
johnsyweb
Como han dicho otros, std::max_element()
y std::min_element()
devolver iteradoresque deben ser desreferenciado para obtener el valor.
La ventaja de devolver un iterador (en lugar de solo el valor) es que le permite determinar el posición del (primer) elemento en el contenedor con el valor máximo (o mínimo).
Por ejemplo (usando C++ 11 por brevedad):
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
std::vector<double> v {1.0, 2.0, 3.0, 4.0, 5.0, 1.0, 2.0, 3.0, 4.0, 5.0};
auto biggest = std::max_element(std::begin(v), std::end(v));
std::cout << "Max element is " << *biggest
<< " at position " << std::distance(std::begin(v), biggest) << std::endl;
auto smallest = std::min_element(std::begin(v), std::end(v));
std::cout << "min element is " << *smallest
<< " at position " << std::distance(std::begin(v), smallest) << std::endl;
}
Esto produce:
Max element is 5 at position 4
min element is 1 at position 0
Nota:
Usando std::minmax_element()
como se sugiere en los comentarios anteriores, puede ser más rápido para grandes conjuntos de datos, pero puede dar resultados ligeramente diferentes. los valores para mi ejemplo anterior sería el mismo, pero la posición del elemento “max” sería 9
ya que…
Si varios elementos son equivalentes al elemento más grande, se devuelve el iterador al último elemento.
-
@synaptik: Esto también debería funcionar con otros tipos de contenedores 🙂
– johnsyweb
15 de abril de 2012 a las 22:46
min/max_element devuelve el iterador al elemento min/max, no al valor del elemento min/max. Debe eliminar la referencia del iterador para obtener el valor y asignarlo a un doble. Eso es:
cLower = *min_element(C.begin(), C.end());
Tenga en cuenta que si está usando C ++ 11, solo puede usar
std::minmax_element
.– GManNickG
15 de abril de 2012 a las 4:51
@GManNickG: No conocía esa función. He agregado una nota a mi respuesta para incorporar esto ya que el comportamiento es diferente.
– johnsyweb
17 de abril de 2012 a las 2:53