2009-01-28 15 views
9

Tengo algunas preguntas sobre el uso de std::map:¿Son estas prácticas apropiadas cuando se trabaja con std :: map?

  1. está utilizando un enum como la clave en std::map una buena práctica? Considere el siguiente código:

    enum Shape{ 
        Circle, 
        Rectangle 
    }; 
    
    int main(int argc, char* argv[]) 
    { 
        std::map<Shape,std::string> strMap; 
        // strMap.insert(Shape::Circle,"Circle"); // This will not compile 
        strMap[Shape::Circle] = "Circle";   // But this will work 
        return 0; 
    } 
    
  2. En el ejemplo anterior, ¿por qué es la llamada a insert() generando un error de compilación, mientras que el operador sobrecargado [] funciona correctamente? ¿Cuál de estos métodos se recomienda para insertar elementos en un std::map?

  3. entiendo que cuando se utiliza el método de la clase find()std::map, que no está haciendo una búsqueda secuencial en el contenedor, pero haciendo un poco de búsqueda logarítmica que será mucho más rápido que la búsqueda secuencial. ¿Es este entendimiento correcto?

Respuesta

12
  1. Tener una enumeración como key_type no es malo por sí mismo. (edit) Pero si solo usa valores de enumeración secuenciales, un std::vector con O (1) acceso es aún mejor.
  2. insert se debe utilizar así: mapVar.insert(make_pair(key, value)); Véase también cppreference.com.
  3. Sí, std::map tiene búsqueda O (log (n)), como lo garantiza el estándar, y esto es más rápido que O (n) si n es suficientemente alto.
+0

cuanto a su edición, no veo muy claro. Imagine que las formas crecen a siete: círculo, rectángulo, triángulo, huevo, lo que sea. Luego tiene una Pieza de clase que tiene una variable de "forma" y desea acceder al valor asignado. Un mapa será más rápido. –

+0

Para Daniel: Como mencionamos los padres, un mapa será más lento ya que es O (logn) frente al tiempo constante del vector. –

+0

Sí, pero tal vez me falta algo. ¡Todo el punto en un mapa es que tiene una clave y busca su valor asignado! Sé que la tecla Círculo y quiero acceder a "Círculo" en el mapa, no puedo hacer eso con un vector. Puedo tener un vector de las teclas y otro de los valores, pero no de búsqueda. –

3

1) Mantener una enumeración como clave en std :: map ¿una buena práctica?

Bueno, para la eficiencia, con una enumeración tan pequeña, sería mejor con un vector o tr1 :: array de cualquiera de los valores (si su tipo de valor admite valores 'vacíos') o punteros inteligentes. ex: vector<string>

Para ser correcto, creo que estás bien. El mapa puede funcionar con cualquier tipo de clave que se pueda ordenar, es decir, que tenga el operador <, o para el que proporcione una función de clasificación. Las Enumeraciones tienen orden por defecto

2) En strMap.insert(Shape::Circle,"Circle") ¿por qué el método de inserción está [dando] un error de compilación?

Porque la inserción no toma dos valores. toma un par. Proveedores:

#include <utility> 
... 
strMap.insert(make_pair(Circle, string("Circle"))); 

3) Cuando se utiliza el método find() en la clase de mapa, [Es] hacer alguna búsqueda logarítmica ... correcto?

Sí. map :: find es O (lg (map :: size())) time. map almacena sus pares clave-valor en una estructura de datos ordenada por clave. insertar y borrar son O (lg (n)), como se encuentra. También proporciona iteradores bidireccionales, lo que significa que puede encontrar el elemento siguiente o anterior en el mapa en O (1) tiempo constante, pero no puede saltar hacia adelante y hacia atrás más de un elemento a la vez.

Edit: corregido que las enum tienen orden por defecto.

+0

Dado que las enumeraciones son enteros, ¿realmente necesita proporcionar un pedido? No lo creo. –

+0

No se puede tener un vector . Puede tener un vector y un vector . Para la búsqueda de valores-clave, necesita un mapa. –

+0

@Daniel - vector _es_ una estructura de datos asociativa. asigna los enteros sin signo secuenciales a los valores. las enumeraciones son enteros sin signo, y son secuenciales por defecto. ver comentarios sobre la respuesta de gimpf – Aaron

1

Intente utilizar

strMap.insert(std::pair<Shape, std::string>(Circle,"Circle")); 

lugar (no Shape :: Círculo!).

valores de enumeración son visibles en el mismo alcance que la enumeración es en C++ (muy feo y yo absolutamente no me gusta nada, pero eso es lo que es!)

5

Insertar falla porque el value_type es std :: pair

+0

¿por qué esta votación fue rechazada? el tipo de valor para el mapa es std :: pair. ¡Ustedes son malos! – Alan

+0

+1 para compensar el downvote innecesario: P. –

0

para situaciones como ésta, en las que a menudo sólo desea una asignación estática de las enumeraciones en cadenas, a menudo es más fácil hacer algo como esto:

enum Shape{ 
    Circle, 
    Rectangle, 
    NShapes, 
}; 

char *ShapeNames[] = 
{ 
    "Circle", 
    "Rectangle",  
}; 

void CheckShapeNames() 
{ 
    // Use a static_assert here instead if you have it in your library 
    int ShapeNamesCount[(sizeof(ShapeNames)/sizeof(char*)) == NShapes]; 
} 

a partir de entonces, el acceso a los nombres de la forma es simple cuestión de acceder a la matriz de ShapeNames:

string name = ShapeNames[Shape::Circle]; 

o incluso:

for (int i=0; i < Shape::NShapes; ++i) 
{ 
    cout << ShapeNames[i]; 
} 
Cuestiones relacionadas